【问题标题】:Way to move files in bash and rename copied file automatically without overwriting an existing file在 bash 中移动文件并自动重命名复制文件而不覆盖现有文件的方法
【发布时间】:2012-01-29 04:51:25
【问题描述】:

我正在对包含大量 jpg 文件的大量目录进行重大重组,其中一些文件与其他目录中的文件同名。我想将文件移动/复制到备用目录,如果名称与该目录中的另一个文件匹配(将 IMG_238.jpg 重命名为 IMG_238_COPY1.jpg、IMG_238_COPY2.jpg 等),bash 会自动重命名它们,而不是覆盖现有文件。

我已经设置了一个脚本,它采用 jpeg 并将它们移动到基于 exif 数据的新目录。移动一个jpg的脚本的最后一行是:mv -n "$JPEGFILE" "$DIRNAME"

我使用 -n 选项是因为我不想覆盖文件,但现在我必须手动对那些没有被移动/复制的文件进行排序。我的 GUI 会自动执行此操作...在 bash 中是否有相对简单的方法来执行此操作?

(以防万一,我在 Mac OSX Lion 中使用 bash 3.2)。

【问题讨论】:

  • 您使用的是什么发行版,还是需要跨发行版?
  • 我正在使用带有 bash 3.2 的 Mac OSX Lion。我会更新我的问题。
  • 您可能想看看fdupes - 它可以帮助您摆脱重复文件,因此您因同名而留下的“未移动”的任何文件都是不同的文件。

标签: macos bash unix scripting file-rename


【解决方案1】:

应该这样做

# strip path, if any
fname="${JPEGFILE##*/}"
[ -f "$DIRNAME/$fname" ] && {
    n=1
    while [ -f "$DIRNAME/${fname%.*}_COPY${n}.${fname##*.}" ] ; do
        let n+=1
    done
    mv "$JPEGFILE" "$DIRNAME/${fname%.*}_COPY${n}.${fname##*.}"
} || mv "$JPEGFILE" "$DIRNAME"

编辑:改进。

【讨论】:

  • 您可以放心删除第一个[ -f "$DIRNAME/$JPEGFILE" ]
  • 你也可以放心弃尾或者|| mv "$JPEGFILE" ...
  • @holygeek:放弃领先的测试和备用 mv 将改变语义。我们不想在所有情况下都添加_COPY${n},仅在需要时添加。 && mv 与 ; mv 完全正确,我在第一次重读时就摆脱了它。
  • 对不起,我的答案在一段时间内有这个条件:while [ -f "$DIRNAME/$JPEGFILE" ]; do ... 在你的答案出现之前,所以我想我建议你简化你的答案,而不是发布一个类似的答案。顺便说一句,如果$JPEGFILE 有路径,mv "$fname" "$DIR..." 在我看来是错误的。
  • @holygeek:你说得对,$fname 在那里不正确。应该是$JPEGFILE。已更正。
【解决方案2】:

您可以尝试 downloading 并查看 Ubuntu/Debian 的基于 Perl 的 rename 是否有效。它具有sed 风格的功能。引用手册页(在我的系统上,但脚本应该与链接的脚本相同):

"rename" 重命名根据指定规则提供的文件名 作为第一个论点。 perlexpr 参数是一个 Perl 表达式 预计至少会修改 Perl 中的 $_ 字符串 指定的文件名。如果给定的文件名没有被 表达式,它不会被重命名。如果没有给出文件名 命令行,文件名将通过标准输入读取。

例如,要重命名所有匹配“*.bak”的文件以去除 扩展,你可能会说

    rename 's/\.bak$//' *.bak

要将大写名称转换为小写,您可以使用

    rename 'y/A-Z/a-z/' *

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-17
    • 1970-01-01
    • 2023-04-09
    • 2020-06-02
    • 1970-01-01
    • 2013-11-24
    • 2021-10-25
    • 1970-01-01
    相关资源
    最近更新 更多