为什么此xargs命令不起作用?


14

我想删除所有.sh扩展名,所以这样做:

ls *.sh | xargs -I {} mv {} `basename {} .sh`

但是,它不起作用,其行为类似于basename返回未更改的文件名。

为什么会这样呢?

例如,这有效:

ls *.sh | xargs -I {} echo `basename {}.jpg .jpg`;

编辑

解决方案:单引号可防止`basename ...`在运行命令之前由外壳进行评估。

ls *.sh | xargs -I {}  sh -c 'mv {} `basename {} .sh`'

Answers:


12

因为basename命令是在管道运行之前运行的。为了使这项工作有效,您需要xargs来执行basename,并且可以使用来实现sh -c,例如:

ls *.sh | xargs -L1 sh -c 'basename $1 .sh' dummy

笔记:

  • 如果您不知道xargs在何处插入文件名,它们将被添加到命令行末尾。
  • 您应该使用-L1开关或等效开关,因此xargs只能将一个参数传递给sh
  • 使用的输出ls可能会产生不良影响

编辑

删除了不推荐使用的选项,谢谢TechZilla


3
您的第一点是错误的,除非您表示该-i选项是默认选项,但是那些“经典”选项已被弃用。例如,仅使用一个选项/行,新的POSIX手册页推荐使用-L1。要调用的旧行为-i,页面建议使用该-I'{}'选项。
JM Becker

因此,它实际上是关于“”而不是“”符号的。我猜想'阻止了外壳评估``。查看我的修改。
majkinetor

@TechZilla:感谢您的更正。@majkinetor:是的,不是,您需要延迟评估,但是我认为您不能使用反引号(`)。
2013年

1
@majkinetor:啊,我明白你的意思了。我想以这种方式重命名文件rename,例如:rename 's/\.sh//' *.sh。首先尝试空运行(-n)。
2013年

1
@majkinetor:rename确实很好用,也很简单,但是请记住它是特定于发行版的。基于RHEL和Debian的发行版提供了不同的rename命令,因此在创建跨发行版脚本时必须牢记这一点。
JM Becker

4

我不确定您的问题,您实际上是在问为什么第一行不起作用吗?或者,您是否正在寻找一种适当的方法来重命名所有.sh文件?

假设这是最干净的方法,我更喜欢在之前准备命令选项xargs。为了删除.sh文件扩展名,我经常考虑采用这种方法,

 find -maxdepth 1 -type f -iname '*.sh'  | sed 'p;s_.sh$__' | xargs -L2 mv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.