从命令中获取详细输出
问题:如何从命令中获取详细输出?
在给定的内容中,有几个命令可以用来获取详细输出。这些命令如下:
find *.txt -exec awk 'END {print $0 "," FILENAME}' {} \; find *.txt -exec sh -c 'echo "$(tail -n 1 "$1"),$1"' _ {} \; find *.txt -exec sh -c 'echo "$(sed -n "\$p" "$1"),$1"' _ {} \;
在这些命令中,我们可以看到有一个下划线(_)出现在大括号({})之前。这个下划线是用来做什么的呢?
有人对这个下划线感到好奇,并提问了它的作用。另外也有人解释说,这个下划线是一个临时变量,用来占位替代$0。举个例子,我们可以用"foobar"替换下划线,然后运行以下命令:
find /usr/bin -name find -exec sh -c 'echo "[$0] [$1]"' foobar {} \;
输出结果为:"[foobar] [/usr/bin/find]",这说明下划线是用来占位的。
有人问道,为什么要使用$1作为参数,而不是$0,是否只是为了可读性的目的?另外也有人解释说,$0通常是程序名(ARGV[0]),$1才是参数。
对于这种方法来说,传递给sh -c的脚本必须要用单引号,而不能用双引号。否则,$1将处于错误的作用域。
另外也有人解释说,引号与此无关,你可以用双引号写成' $1 ',只要你转义变量("\$1")。你还可以转义其他字符("\\"")。
还问说,为什么不将程序名传递给sh,类似这样的写法:find *.txt -exec sh -c '$0 "$(tail -n 1 "$1"),$1"' echo {} \; 或者 find *.txt -exec sh -c 'echo "$(tail -n 1 "$0"),$0"' {} \;?
还有人回答说,这些写法也可以,但是他认为自己的写法更清晰。
这些方法都可以工作,但是没有一种方法是非常清晰的。有人发现,当他试图向别人解释这个命令时,将程序和参数都放在外部更符合逻辑,尽管差别不大。只要这些方法不会破坏其他东西,它们都是合理的。
最后,问为什么要添加一个临时变量而不是使用$0,例如:find *.txt -exec sh -c 'echo "$(sed -n "\$p" "$0"),$0"' {} \;?
对此,有人解释说这是一种一贯使用的模式。有时候需要这样做才能获得正确的行为。可以将以下命令与不带临时变量的相同命令进行比较:sh -c 'echo -e "<$@>\n<$0>\n<$1>\n<$2>"' _ foo bar(正确的输出)。可以看到,没有临时变量时输出是错误的。
我们可以看出,为了获取详细输出,我们可以使用上述命令,并在大括号之前添加一个下划线作为临时变量。这样可以确保正确的输出结果。
问题的原因是使用了嵌入的`{}`变量在shell代码中。这样做是不安全和容易出错的。解决方法是使用参数替代嵌入的变量。
在给出的示例中,使用`find`命令查找当前目录下的所有目录,并执行一个shell命令。在shell命令中,嵌入了`{}`变量来表示找到的目录。然而,嵌入变量的做法是不安全的,因为它容易受到注入攻击。为了解决这个问题,可以使用参数来代替嵌入的变量。
具体的解决方法是使用`find`命令的`-exec`选项来执行一个shell命令,并将参数传递给该命令。通过将参数传递给命令,可以避免使用嵌入的变量。示例中给出了一个使用参数的解决方案:
find . -type d -exec sh -c 'echo -n $0; echo -n " x "; echo $0' "{}" \;
这样,`{}`变量被替换为实际的参数,并且不再嵌入在shell代码中。这样做既更安全,又更可靠。
总结起来,为了避免嵌入变量的安全和可靠性问题,应该使用参数来代替嵌入的变量。这样可以确保命令的执行不会受到注入攻击,并且代码更易于理解和维护。
问题:如何从命令中获取详细输出?
原因:在使用find
命令时,通过-exec
选项可以执行多个子命令。但是默认情况下,第二个子命令只会在第一个子命令成功执行后才会执行。如果希望无论第一个子命令成功与否都执行第二个子命令,可以使用以下方式:
解决方法:使用括号和逻辑运算符-o
来实现,例如:
find . -name "*.txt" \( -exec echo {} \; -o -exec true \; \) -exec grep banana {} \;
另外,如果想要执行两次grep
命令,可以使用以下方式:
find ./* -exec grep -v 'COLD,' {} \; -exec egrep -i "my_string" {} \;
需要注意的是,第二个-exec
命令只有在第一个命令成功执行后才会执行。如果第一个命令返回失败,则第二个命令将被跳过。
如果希望去除echo
命令生成的换行符,可以在echo
命令中使用-n
选项。这对于第二个命令只产生一行输出并希望更易于阅读非常有用。
另外,还可以将第一个-exec
命令的结果通过管道传递给grep
命令,例如:
find . -iname "*.srt" -exec xattr -l {} | grep "" \; > text.txt
如果希望只在第一个命令失败时执行第二个命令,可以使用以下方式:
find . -iname '*.zip' \( -exec unzip {} \; -o -exec 7z x {} \; \)
。在这个例子中,首先尝试使用unzip
解压缩*.zip
文件,如果失败或找不到unzip
命令,则使用7z
来解压缩。
以上就是关于如何从命令中获取详细输出的原因和解决方法的整理。