首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bash:发现sed \ xargs rm不工作,但rm工作

Bash:发现sed \ xargs rm不工作,但rm工作
EN

Stack Overflow用户
提问于 2019-07-10 20:34:21
回答 2查看 434关注 0票数 1

我试图从名为.jssrc的任何子目录中删除所有的__tests____tests__文件。

代码语言:javascript
复制
$ 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

如果出现以下错误,这将失败:

代码语言:javascript
复制
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,复制并粘贴输出并运行它,它就能工作。

代码语言:javascript
复制
$ 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将导致与前面相同的错误。

代码语言:javascript
复制
$ 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。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-11 16:28:30

首先,为了解释这个问题:在find | sed | xargs rm中,shell只设置这些程序之间的通信,但实际上它并不以任何方式处理结果。这是一个问题,因为*.js需要被一个shell展开,用一个文件名列表来替换它;rm将它给出的每个参数都当作一个字面名称来处理。(这与Windows不同,在Windows中,程序自己进行命令行解析和glob扩展)。

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

代码语言:javascript
复制
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匹配的单个文件列表的工作,而不是让这项工作在以后进行:

代码语言:javascript
复制
find src -regextype posix-egrep -regex '.*/__tests__/[^/]*[.]js([.]map)?' -delete
票数 2
EN

Stack Overflow用户

发布于 2019-07-11 06:26:01

您需要扩展您的globs (*)。文件名扩展是由UNIX上的shell执行的,而不是由rm或其他程序执行的。尝试:

代码语言:javascript
复制
.... | 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版本的详细信息)。解决此问题的一种方法是:

代码语言:javascript
复制
find ./src -type d -name __tests__ -exec sh -c '
  for d; do
    rm -- "$d"/*.js{,.map}
  done
' sh {} +
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56978248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档