我想删除除了通过shell脚本的一些目录中的所有文件。 文件的名称将作为命令行parameter passing,参数个数可能会有所不同。
假设目录有这5个文件:
1.txt, 2.txt, 3.txt. 4.txt. 5.txt
我想通过使用文件名的shell脚本从它中删除两个文件。 而且,文件的数量可能会有所不同。
有几种方法可以完成,但大型目录中最强大和性能最高的方法可能是构建一个find
命令。
#!/usr/bin/env bash # first argument is the directory name to search in dir=$1; shift # subsequent arguments are filenames to absolve from deletion find_args=( ) for name; do find_args+=( -name "$name" -prune -o ) done if [[ $dry_run ]]; then exec find "$dir" -mindepth 1 -maxdepth 1 "${find_args[@]}" -print else exec find "$dir" -mindepth 1 -maxdepth 1 "${find_args[@]}" -exec rm -f -- '{}' + fi
此后,列出将被删除的文件(如果上述文件位于名为delete-except
的脚本中):
dry_run=1 delete-except /path/to/dir 1.txt 2.txt
或者,实际删除这些文件:
delete-except /path/to/dir 1.txt 2.txt
我们可以在纯Bash中完成这个工作,而不需要任何外部工具:
#!/usr/bin/env bash # build an associative array that contains all the filenames to be preserved declare -A skip_list for f in "$@"; do skip_list[$f]=1 done # walk through all files and build an array of files to be deleted declare -a rm_list for f in *; do # loop through all files [[ -f "$f" ]] || continue # not a regular file [[ "${skip_list[$f]}" ]] && continue # skip this file rm_list+=("$f") # now it qualifies for rm done # remove the files printf '%s\0' "${rm_list[@]}" | xargs -0 rm -- # Thanks to Charles' suggestion
此解决方案也适用于文件中有空格或者全角字符的文件。
一个简单,直接的方法可能是使用GLOBIGNORE变量。
GLOBIGNORE是一个以冒号分隔的模式列表,用于定义由路径名扩展忽略的一组文件名。 如果由路径名扩展模式匹配的文件名也与GLOBIGNORE中的某个模式相匹配,则将从匹配列表中删除该文件名。
因此,解决方法是遍历命令行参数,将文件名追加到列表中。 然后打电话给rm *。 不要忘记在最后取消设置GLOBIGNORE变量。
#!/bin/bash for arg in "$@" do if [ $arg = $1 ] then GLOBIGNORE=$arg else GLOBIGNORE=${GLOBIGNORE}:$arg fi done rm * unset GLOBIGNORE
*如果您以前设置了GLOBIGNORE,则可以将val存储在tmp var中,然后在最后将其重置。
感谢所有的答案,我已经找到了我的解决方案。 以下是为我工作的解决方案
find / home / mydir -type f | grep -vw“goo”| xargs rm