你有没有想过为什么这个命令不起作用?顺便说一下,我正在尝试剥离当前目录中所有csv文件的扩展名。
find -type f -iname "*.csv" -exec mv {} $(basename {} ".csv") \;
尝试了许多变体,包括参数扩展、xargs...即使这样,一切都是徒劳的。
find ./ -type f -iname "*.csv" -exec sh -c 'mv {} $(basename {} .csv)' \;
find
能够替换 {}
成为它的结果,因为引号阻止了子 Shell 在 find
完成前执行。然后它执行 -exec
部分。
你的命令不能正常工作的问题在于 $(basename {} ".csv")
在一个子 Shell 中执行(-> $()
)并且事先被计算出来了。如果我们逐步查看命令执行过程,你会看到发生了什么:
find -type f -iname "*.csv" -exec mv {} $(basename {} ".csv") \;
- 你的命令find -type f -iname "*.csv" -exec mv {} {} \;
- 子 Shell 已经被计算出来了($(basename {} ".csv")
返回 {}
,因为它将 {}
解释为字面量)find -type f -iname "*.csv" -exec mv {} {} \;
- 现在可以看到:移动实际上什么也没做find
命令会自动递归到任何下面的目录中。$ rename 's/.csv$//' *.csv
find
,也许还需要使用xargs
:$ find . -maxdepth 1 -type f -name "*.csv" | xargs rename 's/.csv$//'
find
和 xargs
使用 null-bytes 进行分隔,这样你就不会因为奇怪的文件名(如带有空格或换行符)而导致进程出错:$ find . -maxdepth 1 -type f -name "*.csv" -print0 | xargs -0 rename 's/.csv$//'
{}
将失败。可以通过使用-exec sh -c 'mv "$1" $(basename "$1" .csv)' sh {} \;
来解决此问题,以便sh
将文件作为参数$1
接收。末尾的额外的sh
是为了将$0
设置为通常设置的sh
。 - John Kugelman-exec
调用sh
并利用$1
时,这为什么很重要? - Arish
时$0
的设置相匹配。这样,您就可以获得与正常情况下相同的错误消息,例如,如果您拼错了mv
,则会出现sh: mvv: command not found
,因为它们都带有"$0: "
前缀。 - John Kugelman