我犯了一个错误,将文件一起转储到同一个目录中。幸运的是,我可以根据文件名对它们进行排序:''' 2019-02-19 20.18.58.ndpi_2_2688_2240.jpg '''在这种特定情况下, #位或2是位置信息。范围是 0-9 并且文件名的长度都相同,因此数字将始终位于文件名的相同位置(第 26 个字符包含空格,两侧是下划线)。我找到了这个很棒的链接: 通过仅搜索部分名称来查找文件的命令?
但是,我无法将输出通过管道传输到 move 命令中。我试图将输出循环到一个变量中,但这似乎也不起作用:
for f in find . -name '*_0_*' ; do mv "$f" /destination/directory ; done
基于此链接,我可能将 * 或一些引号放在了错误的位置:mv: cannot stat No such file or directory in shell script。
也就是说,我有很多目录,我想将它们分类到其他地方的相同目录结构中:
-Flowers (to be sorted) -Flowers-buds -Flowers-stems
-Roses -Roses -Roses
buds.jpg ===> buds.jpg ===> stems.jpg
stems.jpg
petals.jpg
-Daisies -Daisies -Daisies
buds.jpgs buds.jpg stems.jpg
stems.jpg
petals.jpg
-Tulips -Tulips -Tulip
buds.jpgs buds.jpg stems.jpg
stems.jpg
petals.jpg
...以及更多基于该数字(#)。这是在 bash 中实用的操作吗?我在安装了 coreutils 的终端中运行 MacOS,因此这些工具的行为应该像 GNU linux,而不是 darwin (BSD)。
您可以使用
find
and来执行此操作mv
,但这不是这里最简单的方法。你在 macOS 上,所以zsh是预装的。Zsh 带有一个简洁的文件批量重命名工具,称为zmv
. 在终端中运行zsh
,然后在 zsh 中运行类似:说明:
-n
告诉zmv
显示它会做什么,但实际上不做任何事情。当您对它显示的内容感到满意时,再次运行该命令而不使用-n
.zmv
将作用于匹配的文件(并忽略不匹配的文件)。[^_]#
表示除 之外的零个或多个字符_
。Zsh 使您可以访问与 bash 相同的通配符等。#
是一个 zsh-only 功能(在 bash 中可用不同的语法),意思是“任意数量的前一个字符”。该模式[^_]#_[0-9]_*
匹配任何包含两个下划线之间的单个数字且在该数字之前没有其他下划线的文件名。[0-9]
使数字$1
在替换文本中可用。${1}
,${2}
等来指代源模式中带括号的片段,并${f}
指代完整的原始名称。例如,上面的代码片段
2019-02-19 20.18.58.ndpi_2_2688_2240.jpg
移至/elsewhere/2/2019-02-19 20.18.58.ndpi_2_2688_2240.jpg
. 您的问题没有非常精确地描述需要移动的内容以及需要移动到的位置,但是您应该能够通过调整上面的命令来获得所需的内容。如果您无法弄清楚,请编辑您的问题以添加必须匹配和不得匹配的具体示例。如果子目录中有文件,则可以
*/
在模式的开头使用。如果你需要匹配目录来引用它,你需要在: 周围加上括号,你不能在斜杠周围加上括号。如果您想递归地遍历目录并在任何债务处匹配文件,请使用递归globbing。作为一个例外,您需要使用访问替换文本中的目录路径为. 在这种情况下,不使用括号通常更容易,而是使用修饰符将原始路径的部分提取为一个整体。例如,进行与上述相同的重命名,但将文件从当前目录移动到下的并行结构${NUM}
*
**/
(**/)
${NUM}
${f}
/elsewhere
, 但在文件名之前有一个额外的级别0
,等:1
如果很难根据文件名称匹配文件,另一种方法是根据更改时间来匹配它们¹。如果您只是将一堆文件复制到一段时间未更改的目录中,则新文件是最近更改时间的文件。您可以通过在 zsh 中使用glob 限定符
c
更改时间来匹配文件。例如,列出过去一小时内最后更改的文件:您可以使用 glob 限定符(通过增加 ctime 进行排序)和(仅保留前N个匹配项)来引用N个最近更改的文件,而不是查找截止时间。例如,如果您知道您刚刚将 42 个文件移动到该目录中,并且此后没有更改任何内容:
oc
[1,N]
如果您想将 glob 限定符与 一起使用
zmv
,则需要传递该-Q
选项。例如,要将文件移动到基于文件名称的目录,但忽略过去一小时内未更改的所有文件:zmv
有一些安全措施可以检查它是否不会覆盖文件,并且没有冲突(两个源文件具有相同的目标名称)。如果您有大量文件,这些安全措施可能需要一些时间。如果zmv
太慢并且您的重命名结构保证不会发生任何冲突,您可以在循环中对您正在执行的特定重命名进行硬编码。即使您不使用 Zsh,它也倾向于击败 bash,zmv
这要归功于它更好的globbing和参数扩展机制。为了提高性能,您可以动态加载包含用于文件操作的内置函数的模块。例如,将常规文件从当前目录下移动到一个全新的层次结构,如果它们的名称包含
_0_
:(
:h
是另一个 zsh 功能:历史修饰符。)要获取文件名中两个下划线之间的第一个数字,并将文件放在以该数字命名的目录中,您需要提取该数字。
zmv
为带括号的组自动执行此操作,这里我们需要手动执行。如果您想了解其他批量重命名文件的方法,可以浏览此站点上标记的问题
rename
。¹文件的 inode 更改时间,简称“更改时间”或“ctime”,是文件最后一次移动或最后一次更改其属性(例如权限)的时间。它不同于修改时间(mtime)。
外壳在空格上拆分输入。您可以使用带有递归的 bash globbing
**
来正确拆分文件名:如果他们都去同一个地方,则不需要循环:
... 或 use
find -exec
,它将文件名直接从 find 传递给exec()
调用,而不需要 shell 参与:或使用
read
加号find -print0
拆分为空。对于这个问题来说,这是矫枉过正的,在通配时很有用并且find -exec
不能胜任任务:${var#remove_from_start}
要根据文件名更改顶级目标,如您的示例所示,请使用和切断文件名的一部分${var%remove_from_end}
。删除模式中的通配符将尽可能少地删除;要尽可能多地删除,请将操作字符加倍,如${…##…}
or${…%%…}
: