将目录中带有赞助人的文件移动到特定目录

moving files with patron in directories to specific directory

我得到了一堆名称如下的目录(我无法更改生成的任何内容):

yyyy-MM-dd hh.mm.ss DIR1 File 01 random_number/    
yyyy-MM-dd hh.mm.ss DIR2 File 06 random_number/
yyyy-MM-dd hh.mm.ss DIR3 File 11 random_number/
etc

其中 random_number 是一个 11 位随机整数。每个目录都有一个名为 something.ext 的文件(每个目录的名称相同)。还有一个名为 done 的目录,我将已经处理过的目录移动到其中。

我重命名 something.ext 文件并将它们复制到另一个目录,手动像这样:

cd yyyy-MM-dd\ hh.mm.ss\ DIR1\ File\ 01\ random_number/
mv something.ext File\ 01.ext
cp File\ 01.ext /path/to/DIR1/
cd ..
mv yyyy-MM-dd\ hh.mm.ss\ DIR1\ File\ 01\ random_number/ done/

cd yyyy-MM-dd\ hh.mm.ss\ DIR2\ File\ 06\ random_number/
mv something.ext File\ 06.ext
cp File\ 06.ext /path/to/DIR2/
cd ..
mv yyyy-MM-dd\ hh.mm.ss\ DIR2\ File\ 06\ random_number/ done/

etc

有什么方法可以通过脚本自动执行此操作吗?我不太擅长过滤名称和东西...我熟悉 bash 和 python 脚本...

您可以在 for 循环内使用 =~ 运算符进行正则表达式模式匹配,这是从 bashv3+ 开始的 bash 的一个特性。 subshell 在使用 cd 时很有用,不用担心是否以及何时需要退出当前目录。

#!/usr/bin/env bash

regex='^(.+) (.+) (.+) (.+) (.+) (.+)$'

for directory in */; do
  if [[ $directory =~ $regex ]]; then
    dir_num0="${BASH_REMATCH[3]}"
    dir_num1="${BASH_REMATCH[4]} ${BASH_REMATCH[5]}"
    (
      printf 'Going inside directory [%s]\n' "$directory" 
      cd "$directory" || exit
      echo mv -v -- something.txt "$dir_num1.ext" || exit
      echo cp -v -- "$dir_num1.ext" "/path/to/$dir_num0" || exit
    )
    echo mv -v -- "$directory" done/ || exit
  fi
done

对于你给定的样本 input/data 输出是:

Going inside directory [xxx-xx-xx xx.xx.xx DIR3 File 11 x/]
mv -v -- something.txt File 11.ext
cp -v -- File 11.ext /path/to/DIR3
mv -v -- xxx-xx-xx xx.xx.xx DIR3 File 11 x/ done/
Going inside directory [xxx-xx-xx xx.xx.xx DIR1 File 01 xx/]
mv -v -- something.txt File 01.ext
cp -v -- File 01.ext /path/to/DIR1
mv -v -- xxxx-xx-xx xx.xx.xx DIR1 File 01 x/ done/
Going inside directory [xxxx-xx-xx xx.xx.xx DIR2 File 06 x/]
mv -v -- something.txt File 06.ext
cp -v -- File 06.ext /path/to/DIR2
mv -v -- xxxx-xx-xx xx.xx.xx DIR2 File 06 x/ done/

  • =~test/regex运算符支持E.R.E

  • 将脚本放入相关目录并执行。或者将脚本放在 PATH 中,然后进入相关 files/directories 的顶级目录。

  • 如果您对输出满意,请删除 echo

  • regex/patternregex='^(.+) (.+) (.+) (.+) (.+) (.+)$'匹配6个字段space为delimiter/separator。它可以更具体地针对您的目录名称。


类似

regex='^([[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}) ([[:digit:]]{2}\.[[:digit:]]{2}\.[[:digit:]]{2}) (.+) (.+) ([[:digit:]]+) ([[:digit:]]+)/$'

我假设您在初始目录中拥有的只是您的“目录束”加上完成的目录。此外,出于测试目的,我使 /path/to/ 等于 ./done/,以便 /path/to/DIR1/ 等于 ./done/DIR1//path/to/DIR2/ 等于 ./done/DIR2/ , 等等。我的测试目录树如下所示:

$ find .
.
./done
./done/DIR1
./done/DIR2
./done/DIR3
./yyyy-MM-dd hh.mm.ss DIR3 File 11 random_number
./yyyy-MM-dd hh.mm.ss DIR3 File 11 random_number/something.ext
./yyyy-MM-dd hh.mm.ss DIR2 File 06 random_number
./yyyy-MM-dd hh.mm.ss DIR2 File 06 random_number/something.ext
./yyyy-MM-dd hh.mm.ss DIR1 File 01 random_number
./yyyy-MM-dd hh.mm.ss DIR1 File 01 random_number/something.ext
$

您可以通过一个简单的 bash 循环实现您的 mvcp

for i in *; do
    if [ "$i" == "done" ]; then
        continue;
    fi;
    file=$(echo $i | awk '{print  " " }').ext;
    todir=./done/$(echo $i | awk '{print }');
    mv "$i/something.ext" "$i/$file";
    cp "$i/$file" "$todir";
    mv "$i" done;
done

这是运行脚本后的目录树和文件:

$ find .
.
./done
./done/DIR1
./done/DIR1/File 01.ext
./done/DIR2
./done/DIR2/File 06.ext
./done/DIR3
./done/DIR3/File 11.ext
./done/yyyy-MM-dd hh.mm.ss DIR1 File 01 random_number
./done/yyyy-MM-dd hh.mm.ss DIR1 File 01 random_number/File 01.ext
./done/yyyy-MM-dd hh.mm.ss DIR2 File 06 random_number
./done/yyyy-MM-dd hh.mm.ss DIR2 File 06 random_number/File 06.ext
./done/yyyy-MM-dd hh.mm.ss DIR3 File 11 random_number
./done/yyyy-MM-dd hh.mm.ss DIR3 File 11 random_number/File 11.ext
$