重击:查找| sed | xargs rm不起作用,但rm起作用

时间:2019-07-10 20:34:21

标签: bash sed scripting xargs

我正试图从名为.js的{​​{1}}的任何子目录中删除所有.js.mapsrc文件。

__tests__

此操作失败,并出现以下错误:

$ find . -path './src/**' -name __tests__ | # find subdirectories
> sed -E 's/([^ ]+__tests__)/\1\/*.js \1\/*.js.map/g' | # for each subdirectory, concat *.js and *.js.map
> xargs rm # remove files

但是,如果我将rm: cannot remove './src/game/__tests__/*.js': No such file or directory rm: cannot remove './src/game/__tests__/*.js.map': No such file or directory rm: cannot remove './src/helpers/__tests__/*.js': No such file or directory rm: cannot remove './src/helpers/__tests__/*.js.map': No such file or directory 更改为xargs rm,复制并粘贴输出,然后运行它,就可以了。

xargs echo rm

将我的回声的输出包装在$ find . -path './src/**' -name __tests__ | sed -E 's/([^ ]+__tests__)/\1\/*.js \1\/*.js.map/g' | > xargs echo rm # echo command to remove files rm ./src/game/__tests__/*.js ./src/game/__tests__/*.js.map ./src/helpers/__tests__/*.js ./src/helpers/__tests__/*.js.map $ rm ./src/game/__tests__/*.js ./src/game/__tests__/*.js.map ./src/helpers/__tests__/*.js ./src/helpers/__tests__/*.js.map 中并放在$(...)前面会导致与以前相同的错误。

rm

我在做什么错了?

我怀疑这很重要,但是我正在Windows上使用GitBash。

2 个答案:

答案 0 :(得分:2)

首先,解释问题:在find | sed | xargs rm中,shell仅在这些程序之间建立通信,但实际上并没有以任何方式处理结果。这是一个问题,因为*.js需要通过外壳扩展 来替换为文件名列表; rm将给出的每个参数都当作一个文字名称。 (这与Windows不同,在Windows中,程序执行自己的命令行解析和全局扩展)。

可以说,这里根本不需要find。考虑:

shopt -s globstar                 # enable ** as a recursion operator
rm ./src/**/__tests__/*.js{,.map} # delete *.js and *.js.map in any __tests__ directory under src

...或者,如果您想使用find,请让它完成与*.js匹配的单个文件列表的工作,而不是让这项工作稍后发生:

find src -regextype posix-egrep -regex '.*/__tests__/[^/]*[.]js([.]map)?' -delete

答案 1 :(得分:1)

您需要扩展全局(<html> <head> </head> <body> <div> <img id="img1" src="https://cdn.silodrome.com/wp-content/uploads/2013/09/iPhone-5.jpg"> <img id="img2" src="https://i.kinja-img.com/gawker-media/image/upload/s--6tZPLps6--/c_scale,f_auto,fl_progressive,q_80,w_800/trrsg0bnoouitdhsoe0s.jpg" </div> </body> </html>)。文件名扩展由UNIX上的外壳程序执行,而不是由*或其他程序执行。试试:

rm

...对此进行解释:

  • .... | xargs -d $'\n' sh -c 'IFS=; for f; do rm -- $f; done' sh 确保xargs仅在换行符(而不是空格!)上分割,并阻止其将反斜杠和引号视为特殊字符。
  • -d $'\n'作为脚本运行sh -c '...' sh,其中...作为sh,随后的参数在$0中,依此类推; $1因此将遍历这些参数。
  • for f;清除IFS可以防止在不加引号的情况下使用IFS=进行字符串拆分,因此只会发生全局扩展。
  • $f中使用--参数可确保将后续参数视为文件名,而不是选项,即使它们以短划线开头也是如此。

也就是说,如果每个模式确实有很多文件,那么即使使用xargs,也可能会遇到“参数列表过长”的情况。


另一个警告是,包含换行符的文件名可能会拆分为多个名称(取决于您使用的rm版本的详细信息)。可以与find的所有POSIX兼容版本一起使用的解决此问题的方法可能是:

find