【问题标题】:One liner terminal command for renaming all files in directory to their hash values一个线性终端命令,用于将目录中的所有文件重命名为其哈希值
【发布时间】:2021-06-02 09:48:45
【问题描述】:

我是 bash 循环的新手,我试图将目录中的所有文件重命名为相应的 md5 值。

目录中有 5 个示例文件。 出于测试目的,我尝试首先使用以下命令打印目录中所有文件的 md5 哈希,它工作正常。

for i in `ls`; do md5sum $i; done 

输出:

edc47be8af3a7d4d55402ebae9f04f0a  file1
72cf1321d5f3d2e9e1be8abd971f42f5  file2
4b7b590d6d522f6da7e3a9d12d622a07  file3
357af1e7f8141581361ac5d39efa4d89  file4
1445c4c1fb27abd9061ada3b30a18b44  file5

现在我正在尝试通过以下命令使用相应的 md5 哈希重命名每个文件:

for i in `ls`; do mv $i md5sum $i; done

输出失败:

mv: target 'file1' is not a directory
mv: target 'file2' is not a directory
mv: target 'file3' is not a directory
mv: target 'file4' is not a directory
mv: target 'file5' is not a directory

我在这里错过了什么?

【问题讨论】:

  • 当你想要的是for i in *时为什么要调用ls?
  • @stark - 感谢您的评论。两者都工作正常。实际问题在另一个地方。我已经发布了答案。

标签: linux bash terminal


【解决方案1】:

你的命令被扩展为

mv file1 edc47be8af3a7d4d55402ebae9f04f0a file1

mv 有两个以上的非选项参数时,它会将最后一个参数理解为应将所有前面的文件移动到的目标目录。但是没有目录file1

您可以使用参数扩展从字符串中删除文件名。 参数扩展通常比运行cutsed 等外部命令更快,但如果您不重命名数千个文件,这可能没关系。

for f in *; do
    m=$(md5sum "$f")
    mv "$f" ${m%% *}  # Remove everything after the first space
done

还要注意我不解析ls的输出,而是让shell扩展glob。对于包含空格的文件名,它更安全且有效(通过适当的引用)。

【讨论】:

  • 您完全正确。在进行一些反复试验时,我意识到了这个错误。其次,我正在寻找可以直接从终端发射的单线。我试过你的命令for i in *; do m=$(md5sum $i) mv "$i" ${m%% *};done,不知何故它给了我错误。
  • mv前少了一个分号
  • 在进行一些试验时,我也遇到了与您类似的方法,但给了我错误。参考:unix.stackexchange.com/a/102651/232683
  • 我添加了分号,它工作得很好。惊人的!我认为 semi 应该只在 done 部分中完成整个命令时使用。
  • 不,您需要使用换行符或分号来分隔命令。
【解决方案2】:

语法。是的,我给出了错误的语法。

通过对命令的一些尝试和错误,我终于想出了正确的语法。

我注意到 md5sum $i 给了我 2 列输出。

edc47be8af3a7d4d55402ebae9f04f0a  file1
72cf1321d5f3d2e9e1be8abd971f42f5  file2
4b7b590d6d522f6da7e3a9d12d622a07  file3
357af1e7f8141581361ac5d39efa4d89  file4
1445c4c1fb27abd9061ada3b30a18b44  file5

通过触发第二条命令for i in ls; do mv $i md5sum $i; done,我基本上是在告诉终端执行以下操作:

mv $i md5sum $i 

据我所知,结果是

mv file1 <md5 value> file1  <-- this was the issue. 

我是如何解决这个问题的?

我使用cut 命令过滤出所需的值并制作了新的单行,如下所示:

for i in `ls`; do mv $i "$(md5sum $i | cut -d " " -f 1)"; done

[编辑] 根据@stark、@choroba 和@tripleee 的另一个回答和评论,最好使用* 而不是ls。

for i in *;做 mv $i "$(md5sum $i | cut -d " " -f 1)";完成

@choroba 的回答在这里也是一个很好的补充。将其转化为单行需求,以下是他的解决方案:

for i in *;做 m=$(md5sum $i); mv "$i" ${m%% *};完成

猜你喜欢
  • 2017-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
  • 2017-12-19
  • 1970-01-01
相关资源
最近更新 更多