如何在 Mac OSX 上使用 Zsh shell 和 `sed` 命令重命名文件

问题描述 投票:0回答:3

我的桌面上有一个名为“Images”的文件夹,该文件夹内有 3 张图像...

File-A-B.gif
File-C-D.gif
File-E-F.gif

...我想在命令行上重命名文件,以便删除第二个连字符/破折号。所以结果将是这样命名的文件...

File-AB.gif
File-CD.gif
File-EF.gif

...我正在使用相互传输的命令组合,但没有太多运气让它们工作。

最初我有

ls File-* | sed 's/\(File-[^-]\)-\(.+\)/mv & \1\2/' | sh

该命令的分解是...

  • 列出所有以
    File-
  • 开头的文件
  • 将结果通过管道传输至
    sed
  • 我们将使用
    sed
    来捕获名称的不同部分
  • 查看第一个文件,我们将捕获
    File-A
    B.gif
  • 使用
    sed
    然后,我们用移动命令替换匹配的文件名,并有效地告诉它将原始文件重命名为由我们捕获的两条数据组成的文件
  • 然后我们将该命令通过管道传输到
    sh

我收到的最初错误是权限错误。我不知道为什么,因为我对文件有“读写”访问权限。

为了解决这个问题,我

chmod 777
每个文件。

这导致了一个新的错误,即

cannot execute binary file

为了解决该错误,我看到了这篇文章:http://blog.mpdaugherty.com/2010/05/27/difference-with-sed-in-place-editing-on-mac-os-x-vs- linux/ 建议添加一对额外的单引号。这样做的原因(显然)是因为

sed
会出错,因为它不知道要使用什么文件扩展名,但是放置一个空字符串可以消除该错误(旁注:我的理解是您还需要使用
-i
标志 - 我没有使用 - 但这样做会导致不同的错误,所以我放弃了它并只使用单引号来避免我遇到的二进制文件错误)。

所以现在我有

ls File-* | sed '' 's/\(File-[^-]\)-\(.+\)/mv & \1\2/' | sh

但这会出错

No such file or directory

我试图明确文件的位置,例如......

ls File-* | sed '' 's/\(File-[^-]\)-\(.+\)/mv ~\/Desktop\/Images\/& ~/Desktop\/Images\/\1\2/' | sh

...注意我必须转义正斜杠

~\/Desktop\/Images\/
但这仍然不起作用。

我还使用 Homebrew 安装了 GNU 版本的

sed
,但它也以类似的方式出现错误
gsed: can't read s/\(Vim-[^-]\)-\(.+\)/mv & \1\2/: No such file or directory

我对如何让它发挥作用有点不知所措。

我不想不得不编写 bash/zsh 脚本或 Ruby 脚本。

您能给我的任何帮助将不胜感激。

macos shell sed zsh
3个回答
10
投票

如果您使用

zsh
,则不需要使用
sed
:有一个名为 zmv
zsh 模块可以非常简单地实现此目的:

$ ls -F -G
File-A-B.gif  File-C-D.gif  File-E-F.gif

$ zmv -n 'File-(*)-(*).gif' 'File-${1}${2}.gif'
mv -- File-A-B.gif File-AB.gif
mv -- File-C-D.gif File-CD.gif
mv -- File-E-F.gif File-EF.gif

注意: 省略

-n
以使其实际运行。

它的工作原理是匹配括号内的内容。在这种情况下:

File-(*)-(*).gif
都会匹配
File-A-B.gif
并保存
A
B
以便我们以后可以参考它们。然后,我们将刚刚匹配的文件移动到新文件名,省略两个字母之间的连字符并使用引用插入字母:
File-${1}${2}.gif

这是一个非常强大的小模块,只要您可以给它两个正则表达式:一个用于匹配要重命名的文件,第二个用于匹配重命名的文件名。


3
投票

以下内容应该适合您:

ls File-* | sed 's/\(.*\)-\(.*\)/mv & \1\2/' | sh

你尝试了什么

ls File-* | sed '' 's/\(File-[^-]\)-\(.+\)/mv & \1\2/' | sh

非常接近。说:

ls File-* | sed '' 's/\(File-[^-]*\)-\(.*\)/mv & \1\2/' | sh

相反会有效。


0
投票

另一种方法是使用 mv,例如:

mv <current-filename> <new-filename> 
© www.soinside.com 2019 - 2024. All rights reserved.