如何在 find exec 中回显 shell 中的单引号
How to echo single quotes from within shell in find exec
编辑
在以下答案之间,chepner 和 Walter_A 解决了问题。简而言之,要从查找命令中打印单引号,您
(1) 使用 "\047" 代替单引号或
(2) 定义一个局部变量,例如q="'" 就在查找命令之前,并使用 $q 而不是单引号。
因此,这个特定问题的解决方案不是使用 printf 代替 echo 或 for 循环代替 find...exec,而是两者printf 和 for 可能有助于改进代码。
原始问题:
我正在尝试使以下过程自动化:
在当前目录中查找某些文件;
为每个文件名在文本文件中附加一行,其中文件名前面有字符串 "file " 并用单引号括起来。
这实际上是任务的简化版本:我搜索的文件是视频文件,ffmpeg 在尝试将它们的名称写入文本文件之前对它们做了一些处理。文本文件的目的是稍后连接输出文件。完整的行是这样的:
find . -maxdepth 1 -iname "name*" -exec sh -c 'ffmpeg -i "[=11=]" -ss 3.3 -c:v libx264 -crf 20 -pix_fmt yuv420p -c:a copy "out/""[=11=]"; echo "file ""\'""$(basename -- "[=11=]")">>mylist.txt' {} \;
但是,视频部分效果很好,我只关注单引号的打印(在屏幕上或文件中),这给我带来了麻烦。如果我试试这个:
find . -iname "*" -exec sh -c 'echo "file ""[=12=]"' {} \;
我得到了,如预期的那样:
file a1.mp4
file a2.mp4
[...]
我现在在文件名$0前加上单引号;在双引号或单引号之间,是否转义(如果转义,我也尝试过不带引号),在美元符号后的引号之间,但我得到的只是符号“>”后跟闪烁的光标,等待更多输入。
我尝试将单引号插入为:"\'", '\'', \', $''', $'\'', $"\'";
我把它放在字符串 "file " 中,带或不带单引号或双引号;我在 exec 中设置了一个变量 v="file ""\'""$0" 并在双引号之间回显了 it。不过,我所有的尝试都失败了。最好理解为什么。或许这里有值得学习的地方。。。谢谢大家的指点。
______________ 解决方法 _______________
我找到了解决方法。我写了一个 bash 文件,而不是从终端发出单个命令。在查找行之前,我导出一个变量 SQ="'"。然后我的查找行变成:
find . -maxdepth 1 -iname "*" -exec sh -c 'echo "file ""$SQ""$(basename -- "[=14=]")""$SQ"' {} \;
并且有效。也许出现在导出变量中的单引号与出现在 shell 或局部变量中的字符串中的单引号的处理方式不同?
使用 printf
而不是 echo
。
find . -iname "*" -exec printf "file '%s'" {} \;
为避免为每个文件分叉外部 printf
,使用 sh
访问 shell 内置函数,使用
find . -iname "*" -exec sh -c 'for f; do printf "file 7%s7\n" "$f"; done' sh {} +
shell 和 +
终止符中的循环确保 sh
将 运行 尽可能少。通过使用 7
指示 printf
输出单引号可以避免引用问题。
更新:我会用一个简单的 shell 循环替换 find
。
for full in name*; do
f=$(basename "$full")
ffmpeg -i "$full" -ss 3.3 -c:v libx264 -crf 20 -pix_fmt yuv420p -c:a copy "out/$f"
printf "file '%s'\n" "$f" >> mylist.txt
done
这行不是做同样的事情吗?
find . -iname "*" -exec sh -c 'echo "file" "$(basename [=10=])"' {} \;
要在一对单引号内插入一个单引号,请使用 '"'"'
:
find . -maxdepth 1 -iname "*" -exec sh -c 'echo "file '"'"'$(basename -- "[=10=]")'"'"'"' {} \;
'"'"'
的解释:
第一个 '
关闭前一个单引号
"'" 插入单引号
最后 '
重新启动单引号字符串。
为临时变量分配引号(我也删除了路径)。
q="'" find . -iname "*" -exec sh -c 'echo "file $q${0##*/}$q"' {} \;
编辑
在以下答案之间,chepner 和 Walter_A 解决了问题。简而言之,要从查找命令中打印单引号,您
(1) 使用 "\047" 代替单引号或
(2) 定义一个局部变量,例如q="'" 就在查找命令之前,并使用 $q 而不是单引号。
因此,这个特定问题的解决方案不是使用 printf 代替 echo 或 for 循环代替 find...exec,而是两者printf 和 for 可能有助于改进代码。
原始问题:
我正在尝试使以下过程自动化:
在当前目录中查找某些文件;
为每个文件名在文本文件中附加一行,其中文件名前面有字符串 "file " 并用单引号括起来。
这实际上是任务的简化版本:我搜索的文件是视频文件,ffmpeg 在尝试将它们的名称写入文本文件之前对它们做了一些处理。文本文件的目的是稍后连接输出文件。完整的行是这样的:
find . -maxdepth 1 -iname "name*" -exec sh -c 'ffmpeg -i "[=11=]" -ss 3.3 -c:v libx264 -crf 20 -pix_fmt yuv420p -c:a copy "out/""[=11=]"; echo "file ""\'""$(basename -- "[=11=]")">>mylist.txt' {} \;
但是,视频部分效果很好,我只关注单引号的打印(在屏幕上或文件中),这给我带来了麻烦。如果我试试这个:
find . -iname "*" -exec sh -c 'echo "file ""[=12=]"' {} \;
我得到了,如预期的那样:
file a1.mp4
file a2.mp4
[...]
我现在在文件名$0前加上单引号;在双引号或单引号之间,是否转义(如果转义,我也尝试过不带引号),在美元符号后的引号之间,但我得到的只是符号“>”后跟闪烁的光标,等待更多输入。
我尝试将单引号插入为:"\'", '\'', \', $''', $'\'', $"\'"; 我把它放在字符串 "file " 中,带或不带单引号或双引号;我在 exec 中设置了一个变量 v="file ""\'""$0" 并在双引号之间回显了 it。不过,我所有的尝试都失败了。最好理解为什么。或许这里有值得学习的地方。。。谢谢大家的指点。
______________ 解决方法 _______________
我找到了解决方法。我写了一个 bash 文件,而不是从终端发出单个命令。在查找行之前,我导出一个变量 SQ="'"。然后我的查找行变成:
find . -maxdepth 1 -iname "*" -exec sh -c 'echo "file ""$SQ""$(basename -- "[=14=]")""$SQ"' {} \;
并且有效。也许出现在导出变量中的单引号与出现在 shell 或局部变量中的字符串中的单引号的处理方式不同?
使用 printf
而不是 echo
。
find . -iname "*" -exec printf "file '%s'" {} \;
为避免为每个文件分叉外部 printf
,使用 sh
访问 shell 内置函数,使用
find . -iname "*" -exec sh -c 'for f; do printf "file 7%s7\n" "$f"; done' sh {} +
shell 和 +
终止符中的循环确保 sh
将 运行 尽可能少。通过使用 7
指示 printf
输出单引号可以避免引用问题。
更新:我会用一个简单的 shell 循环替换 find
。
for full in name*; do
f=$(basename "$full")
ffmpeg -i "$full" -ss 3.3 -c:v libx264 -crf 20 -pix_fmt yuv420p -c:a copy "out/$f"
printf "file '%s'\n" "$f" >> mylist.txt
done
这行不是做同样的事情吗?
find . -iname "*" -exec sh -c 'echo "file" "$(basename [=10=])"' {} \;
要在一对单引号内插入一个单引号,请使用 '"'"'
:
find . -maxdepth 1 -iname "*" -exec sh -c 'echo "file '"'"'$(basename -- "[=10=]")'"'"'"' {} \;
'"'"'
的解释:
第一个 '
关闭前一个单引号
"'" 插入单引号
最后 '
重新启动单引号字符串。
为临时变量分配引号(我也删除了路径)。
q="'" find . -iname "*" -exec sh -c 'echo "file $q${0##*/}$q"' {} \;