bash 用于从父文件夹名称重命名多个文件的 Shell 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4861208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:22:29  来源:igfitidea点击:

Shell script to rename multiple files from their parent folders name

linuxbashshellscriptingrename

提问by Simon

I have a file structure like this:

我有这样的文件结构:

  • 00000010
    • 000000001.file1
    • 000000001.file2
  • 00000020
    • 00000003.file1
    • 00000003.file2
    • 00000003.file3
  • ...
  • 00000010
    • 000000001.file1
    • 000000001.file2
  • 00000020
    • 00000003.file1
    • 00000003.file2
    • 00000003.file3
  • ...

So there are folders with 8-digit names containing one ore more files with name starting with 8-digit numbers. But theses filenames are – let's say – out of sync. So Now I try to rename them recursively in bash to archive:

因此,存在名称为 8 位数字的文件夹,其中包含一个或多个名称以 8 位数字开头的文件。但是这些文件名 - 比方说 - 不同步。所以现在我尝试在 bash 中递归地重命名它们以存档:

  • 00000010
    • 000000010.file1
    • 000000010.file2
  • 00000020
    • 00000020.file1
    • 00000020.file2
    • 00000020.file3
  • ...
  • 00000010
    • 000000010.file1
    • 000000010.file2
  • 00000020
    • 00000020.file1
    • 00000020.file2
    • 00000020.file3
  • ...

My script does look like:

我的脚本看起来像:

#! /bin/bash

find * -maxdepth 1 -name "*" -type d | while read -r dir
do
        rename 's/$dir\/[0-9]{8}/$dir/' *
done

But this is not working and gives errors like

但这不起作用,并给出了类似的错误

Global symbol "$dir" requires explicit package name at (eval 1) line 1.

全局符号“$dir”需要在(eval 1)第 1 行显式包名。

How could I write it to rename the files according to their folder names?

我怎么能写它根据文件夹名称重命名文件?

Thank you for help!

谢谢你的帮助!

回答by codaddict

Use "in place of 'in rename

使用"代替'rename

You should run renameon the files inside $dir, so the argument to renamemust be $dir/*and not just *

你应该运行rename里面的文件$dir,所以参数rename必须是$dir/*,而不仅仅是*

Since you want to replace dir/8digitswith dir/dirthe replacement part of the regex should be $dir\/$dir

既然你想dir/8digitsdir/dir正则表达式的替换部分替换应该是$dir\/$dir

With the above changes the command looks like:

通过上述更改,命令如下所示:

rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*

回答by Mikel

renameis actually a Perl script.

rename实际上是一个 Perl 脚本。

Here's how you could do it using only bashand mv:

以下是仅使用bashand 的方法mv

#!/bin/bash

for dir in *; do
    if test -d "$dir"; then
        (
            cd $dir
            for file in *; do
                newfile=$dir.${file#*.}
                mv "$file" "$newfile"
            done
        )
    fi
done

First a script to reproduce your directory tree:

首先是一个脚本来重现您的目录树:

$ i=1
$ for dir in 000000{1..2}0; do
mkdir $dir
touch $dir/0000000$i.file{1..3}
i=$((i+1))
done
$ find .
.
./00000010
./00000010/00000001.file1
./00000010/00000001.file2
./00000010/00000001.file3
./00000020
./00000020/00000002.file3
./00000020/00000002.file2
./00000020/00000002.file1

And now showing the script working:

现在显示脚本工作:

$ ../ren.sh
$ find .
.
./00000010
./00000010/00000010.file1
./00000010/00000010.file2
./00000010/00000010.file3
./00000020
./00000020/00000020.file1
./00000020/00000020.file2
./00000020/00000020.file3

回答by sarnold

First, *in your find command is misplaced -- you need to give a directory to start searching. .is usual.

首先,*在您的 find 命令中放错了位置——您需要提供一个目录才能开始搜索。.很平常。

Second, $dirin your perl rename command won't be expanded by the shell because the whole string is quoted.

其次,$dir在您的 perl rename 命令中,shell 不会扩展,因为整个字符串都被引用了。

Third, the *you are handing to your perl rename command will expand to all the directories and filesin your current working directory, which is probably not what you intended.

第三,*您正在执行的 perl rename 命令将扩展到您当前工作目录中的所有目录和文件,这可能不是您想要的。

@Mikel's answer is much nicer than what I was working on, but I thought this might still be useful. :)

@Mikel 的回答比我正在做的要好得多,但我认为这可能仍然有用。:)