bash:展开参数列表并将其传递给find-escapping/white-spaces-hell



我想检查文件夹中的文件并删除其中的一些。一个条件是保留特定类型的所有文件(例如.txt),并保留具有第一次搜索名称但具有不同扩展名的所有文件。目录中的所有其他文件都应删除。

这可以通过find . -type f -not -name xxx命令容易地实现。但是,我想为自动找到的每个[第一次搜索的名称]填充find命令。

为了做到这一点,我写了这个litte脚本

#!/bin/bash
while read filename; do
filename=$(echo $filename | sed 's/ /\ /g')
filename='$filename*'
file_list=$file_list" -not -name $filename"
done <<<"$(ls *.txt | sed 's/.txt//g')"
find . -type f $file_list -print0| while read -d $'' FILE
do
rm -f "$FILE"
done

$file_list很好地填充了相应的数据,但是,find失败了,显示:

find:未知谓词`-\'

如果我使用sed命令(''->'\')或

find:路径必须在表达式之前:-用法:find[-H][-L][-p][-Olevel][-D[help|tree|search|stat|rates|opt|exec][path…][表达式]

如果我对sed行进行注释。

bash-x向我展示了以下已执行的命令:

没有sed命令:

查找-type f-not-name"\"Text"-here-or-there*">

使用sed命令:

查找-在此处键入f-not-name"或"文本"'there*'\'''

这在find中可能吗?我还尝试在find命令中逃离$find_list,但没有成功。

使用数组,而不是字符串。

#!/bin/bash
# ^-- must be /bin/bash, not /bin/sh, for this to work
excludes=( )
for filename in *.txt; do
excludes+=( -not -name "${filename%.txt}" )
done
find . -type f -not -name '*.txt' "${excludes[@]}" -exec rm -f '{}' +

要了解为什么这样做,请参阅BashFAQ#50。


现在,如果你想与/bin/sh兼容,而不仅仅是bash,那么把它封装在一个函数中,这样你就可以覆盖参数列表(这是唯一可用的数组),而不会丢弃脚本的全局参数:

delete_except_textfiles() {
local filename 2>/dev/null ||: "local keyword not in POSIX, ignore if not present"
set --
for filename in *.txt; do
set -- "$@" -not -name "${filename%.txt}"
done
find . -type f -not -name '*.txt' "$@" -exec rm -f '{}' +
}
delete_except_textfiles

试试这个

#!/bin/bash
remove_except()
{
local extension=$( printf "%q" "$1" )
local dir=$( printf "%q" "$2" )
local start_dir=$(pwd)
[ -z "$extension" ] && return 1
[ -z "$dir" ] || [ ! -d "$dir" ] && dir="."
cd "$dir"
local this="$0"
this="${this##*/}"
# exclude myself and extension
local excludes=" -name "$this" -o -name "*.$extension" "
for f in *."$extension";
do
filename="${f%.*}"
excludes="$excludes -o -name "$filename.*""
done
eval "find . -maxdepth 1 -type f -not ( $excludes ) -print0" | xargs -0 -I {} rm -v {}
cd "$start_dir"
}
remove_except "txt" "/your/dir"

放入一个脚本中,例如remove_except.sh,并像这样运行:

remove_except.sh "txt" "/your/dir"

第二个参数是可选的,如果未指定,则假定为.

相关内容

  • 没有找到相关文章

最新更新