我试图从名为.js的src的任何子目录中删除所有的__tests__和__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将导致与前面相同的错误。
$ rm $(find . -path './src/**' -name __tests__ | sed -E 's/([^ ]+__tests__)/\1\/*.js \1\/*.js.map/g' | xargs echo rm
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我做错了什么?
我怀疑这有什么关系,但我在Windows上使用GitBash。
发布于 2019-07-11 16:28:30
首先,为了解释这个问题:在find | sed | xargs rm中,shell只设置这些程序之间的通信,但实际上它并不以任何方式处理结果。这是一个问题,因为*.js需要被一个shell展开,用一个文件名列表来替换它;rm将它给出的每个参数都当作一个字面名称来处理。(这与Windows不同,在Windows中,程序自己进行命令行解析和glob扩展)。
可以说,这里根本不需要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...or,如果您确实想使用find,那么让它做一个与*.js匹配的单个文件列表的工作,而不是让这项工作在以后进行:
find src -regextype posix-egrep -regex '.*/__tests__/[^/]*[.]js([.]map)?' -delete发布于 2019-07-11 06:26:01
您需要扩展您的globs (*)。文件名扩展是由UNIX上的shell执行的,而不是由rm或其他程序执行的。尝试:
.... | xargs -d $'\n' sh -c 'IFS=; for f; do rm -- $f; done' sh...to解释如下:
-d $'\n'确保xargs只在换行符(而不是空格!)上拆分,并阻止它将反斜杠和引号作为特殊处理。sh -c '...' sh以脚本形式运行...,以sh作为$0运行,在$1中运行后续参数等等;因此,for f;将迭代这些参数。IFS=清除IFS=可以防止在未引用$f时发生字符串分裂,因此只有glob扩展发生。--参数来rm确保它将后续参数作为文件名,而不是选项,即使它们以破折号开头。也就是说,如果每个模式都有大量文件,那么即使使用xargs,也可能会遇到“参数列表太长”。
另一个警告是,包含换行符的文件名可能被拆分为多个名称(取决于您正在使用的find版本的详细信息)。解决此问题的一种方法是:
find ./src -type d -name __tests__ -exec sh -c '
for d; do
rm -- "$d"/*.js{,.map}
done
' sh {} +https://stackoverflow.com/questions/56978248
复制相似问题