问题

问题

我尝试学习 shell 脚本的新技能。所以现在我从老师那里得到了关于将文件移动到新目录的课程。

问题

有一个文件模式

A_20180423_0015  B_20180501_0045  C_20180426_0045  

并想要将文件移动到 /new/destpath/A/20180423/0015,0030,0045 等目录,每个目录有 3 个文件

在我的脚本中我写

 #! /bin/bash
cd /app/Moving/DEST_PATH
mkdir A B C D
cd /app/Moving/DEST_PATH/A
MakesubA=$(for itype in A;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/B
MakesubB=$(for itype in B;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/C
MakesubC=$(for itype in C;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/D
MakesubD=$(for itype in D;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..

我尝试找出使用循环或其他方法,但我不知道使用哪个来将每个文件选择到每个目录。

答案1

您的文件基本上在文件名中编码了目标路径。

被调用的文件A_20180423_0015应该移动到A/20180423/0015(我假设0015是目录中文件的新名称A/20180423),这是一个与原始文件名相同的路径名,但下划线替换为斜杠。

这意味着本练习是关于替换字符串中的字符。

无需为每个可能的日期遍历并创建目标目录,因为目标已经编码在文件的文件名中。

我不完全确定原始文件位于哪里,或者您是否可以用作[A-Z]_*_*模式来匹配当前目录中的它们(我假设您可以)。

for source_filename in [A-Z]_*_*; do
    target_pathname=${source_filename//_//}
    mkdir -p "${target_pathname%/*}"
    mv "$source_filename" "$target_pathname"
done

如果我们开始

.
|-- A_20180423_0015
|-- B_20180501_0045
`-- C_20180426_0045

0 directory, 3 files

...并运行上面的代码,然后我们将得到

.
|-- A/
|   `-- 20180423/
|       `-- 0015
|-- B/
|   `-- 20180501/
|       `-- 0045
`-- C/
    `-- 20180426/
        `-- 0045

6 directories, 3 files

注释代码:

# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
    # Replace all underscores in the found name with slashes.
    # We use bash's ${parameter//pattern/replacement} pattern substitution
    # to do this.
    # If you need to append a path to this, just do so with
    #    target_pathname="/some/path/${source_filename//_//}"
    target_pathname=${source_filename//_//}

    # Make sure that the target directory exists.
    # With ${target_pathname%/*} we remove the filename component of
    # the target pathname to get the directory of the destination file.
    # You may change this to the following if you wish:
    #     mkdir -p "$( dirname "$target_pathname" )"
    mkdir -p "${target_pathname%/*}"

    # Move the file into place.
    mv "$source_filename" "$target_pathname"
done

如果我误解了这个问题,并且文件应该保留其原始文件名,但应该移动到与文件名对应的目录中,即A_20180423_0015应该移动到A/20180423/0015/A_20180423_0015,那么我们只需更改上面代码中的几个字符:

mkdir -p "${target_pathname%/*}"

更改为

mkdir -p "$target_pathname"

这个改变会给我们带来

.
|-- A/
|   `-- 20180423/
|       `-- 0015/
|           `-- A_20180423_0015
|-- B/
|   `-- 20180501/
|       `-- 0045/
|           `-- B_20180501_0045
`-- C/
    `-- 20180426/
        `-- 0045/
            `-- C_20180426_0045

9 directories, 3 files

对于源文件位于当前目录之外的另一个目录的情况:

for source_pathname in /some/source/path/[A-Z]_*_*; do
    source_filename=${source_pathname##*/}
    target_pathname="some/target/path/${source_filename//_//}"
    mkdir -p "$target_pathname"
    mv "$source_pathname" "$target_pathname"
done

相关内容