我编写了一个 Bash 脚本,mscript.sh
用于管理我的音乐文件,其中一部分创建了此类文件的列表。
all_exts=" -iname \"*.webm\" -o -iname \"*.mkv\" "
#all_exts=' -iname "*.webm" -o -iname "*.mp3" -o -iname "*.mp4" -o -iname "*.mkv" '
#The line below works fine
#find "${HOME}/pCloudDrive/SocialSciences/Arabic/al_aghani" -maxdepth 1 -type f -size +1M \( -iname "*.webm" -o -iname "*.mp3" -o -iname "*.mp4" -o -iname "*.mkv" \)|\
find "${HOME}/pCloudDrive/SocialSciences/Arabic/al_aghani" -maxdepth 1 -type f -size +1M \( "$all_exts" \)|\
awk -v FS="/" '{print $8}' > "${HOME}/pCloudDrive/SocialSciences/Arabic/al_aghani/list"
#it does not work with single quotes either
我得到以下输出,
find: paths must precede expression: -iname "*.webm" -o -iname "*.mkv" '
当我运行脚本而不尝试插入all_exts
我的 find 命令时,脚本工作正常。我如何正确扩展all_exts
? PS 这个脚本很简单只是为了隔离问题。我确实需要插入all_exts
find 命令,因为我有许多 find 命令在许多不同的目录中执行这项工作。
答案1
这是因为,既然您应该引用该变量,那么它就会将单个字符串传递给find
.您可以通过以下方式查看set -x
:
$ all_exts=" -iname \"*.webm\" -o -iname \"*.mkv\" "
$ set -x
$ find . "$all_exts" > /dev/null
+ find . ' -iname "*.webm" -o -iname "*.mkv" '
不幸的是,你不能不引用它。首先是因为这可能很危险所以最好不要养成这种习惯,其次是因为它在这里不起作用,因为如果您不引用表达式,shell 会将其拆分并将其find
作为单独的带引号的字符串传递给:
$ find . $all_exts
+ find . -iname '"*.webm"' -o -iname '"*.mkv"'
因此,这将查找名为 的文件"foo.webm"
,其中引号是文件名的一部分。将此类参数作为变量传递给命令的正确方法是使用数组并将带引号的数组传递给find
:
$ all_exts=( '-iname' '*.webm' '-o' '-iname' '*.mkv' )
$ find . \( "${all_exts[@]}" \)
+ find . '(' -iname '*.webm' -o -iname '*.mkv' ')'
./foo.webm