我是这里的新手,请耐心等待。
我有一个包含数千个文件的目录。文件名始终以 1 或 2 个字母开头,下划线“_”之前有 4 个字符。每个模式的文件数量可以不同,文件名下划线后的部分会发生变化。
样本:
Parentdir:
->AA01_*.pdf
->AA01_*.html
->AA01_*.txt
...
->ZZ99_*.pdf
->ZZ99_*.html
->ZZ99_*.txt
...
->A001_*.pdf
->A001_*.html
->A001_*.txt
...
->Z999_*.pdf
->Z999_*.html
->Z999_*.txt
我想运行一个命令,仅使用文件名中的字母创建新目录,并用以这些字母开头的文件填充它们。如果目标目录中有一个同名的文件(源目录中的更新文件),我想保留最新的文件。所以:
New dir/files:
->AA
AA01_*.pdf
AA01_*.html
AA01_*.txt
...
->ZZ
ZZ99_*.pdf
ZZ99_*.html
ZZ99_*.txt
...
->A
A001_*.pdf
A001_*.html
A001_*.txt
...
->Z
Z999_*.pdf
Z999_*.html
Z999_*.txt
这能实现吗?
谢谢!
答案1
遍历文件集。选择字母前缀。创建目录(如果需要)并将文件移入其中。
#!/bin/sh
for item in *
do
if [ -f "$item" ]
then
prefix="$(echo "$item" | sed 's/[^A-Z].*//')"
echo mkdir -p "$prefix"
echo mv "$item" "$prefix/"
fi
done
删除echo
前缀mkdir
,mv
当您满意时,它就会执行您想要的操作。
答案2
使用珀尔 rename
实用程序(在某些 Linux 发行版上prename
又称为file-rename
, perl-rename
):
rename -n 'if (m/^(\w{1,2}?)(\d{2,}_.*)/) {mkdir $1; $_ = "$1/$1$2"}' *
注意:这有效仅有的使用基于 perl 的重命名实用程序。您可以通过运行rename -V
(或prename -V
或file-rename -V
或)来检查是否已安装它perl-rename -V
。如果提到了 perl 或File::Rename
,那么它就是 的 perl 版本rename
。否则,rename
它可能是util-linux
完全不同的不相容功能和命令行选项。这会不是使用 util-linux 的 rename (或任何其他版本的 rename - 它)需要Perl 重命名)
这使用每个匹配文件名的前一个或两个“单词”字符(非贪婪匹配)作为目录,然后创建目录,并将文件重命名到目录中。 “单词”字符 ( \w
) 的定义man perlre
如下:
“匹配“单词”字符(字母数字加“_”,加上其他连接标点符号加 Unicode 标记)”
如果这不是您想要的,您可以使用例如[[:alpha:]]{1,2}?
代替\w{1,2}?
任何字母字符或[[:upper:]]{1,2}
仅大写字符来优化模式。
这\d
数字。如果你想允许任何下划线之前的单词字符,使用\w
.或者,[[:alnum:]]
如果您只想允许字母和数字字符,请使用。
与整个模式不匹配的文件名(1 个或 2 个“单词”字符,后跟至少两个数字,后跟下划线)不受影响。
注:-n
选项使其成为空运行操作。它只会显示它的内容会做,但没有真正做。一旦您确定它满足您的要求,请删除-n
(或将其替换-v
为详细输出)。
例如给出以下设置脚本:
#!/bin/bash
for i in A AA Z9 ZZ ; do
for j in {01..10} ; do
touch "$i${j}_.txt"
done
done
# anomaly
touch A1001_.txt
$ ./setup.sh
$ ls
A01_.txt A02_.txt A03_.txt A04_.txt A05_.txt A06_.txt A07_.txt A08_.txt
A09_.txt A1001_.txt A10_.txt AA01_.txt AA02_.txt AA03_.txt AA04_.txt AA05_.txt
AA06_.txt AA07_.txt AA08_.txt AA09_.txt AA10_.txt setup.sh* Z901_.txt
Z902_.txt Z903_.txt Z904_.txt Z905_.txt Z906_.txt Z907_.txt Z908_.txt
Z909_.txt Z910_.txt ZZ01_.txt ZZ02_.txt ZZ03_.txt ZZ04_.txt ZZ05_.txt
ZZ06_.txt ZZ07_.txt ZZ08_.txt ZZ09_.txt ZZ10_.txt
运行 perl 重命名脚本后:
$ rename 'if (m/^(\w{1,2}?)(\d{2,}_.*)/) {mkdir $1; $_ = "$1/$1$2"}' *
$ ls */*
A/A01_.txt A/A02_.txt A/A03_.txt A/A04_.txt A/A05_.txt A/A06_.txt
A/A07_.txt A/A08_.txt A/A09_.txt A/A1001_.txt A/A10_.txt AA/AA01_.txt
AA/AA02_.txt AA/AA03_.txt AA/AA04_.txt AA/AA05_.txt AA/AA06_.txt
AA/AA07_.txt AA/AA08_.txt AA/AA09_.txt AA/AA10_.txt Z/Z901_.txt
Z/Z902_.txt Z/Z903_.txt Z/Z904_.txt Z/Z905_.txt Z/Z906_.txt Z/Z907_.txt
Z/Z908_.txt Z/Z909_.txt Z/Z910_.txt ZZ/ZZ01_.txt ZZ/ZZ02_.txt ZZ/ZZ03_.txt
ZZ/ZZ04_.txt ZZ/ZZ05_.txt ZZ/ZZ06_.txt ZZ/ZZ07_.txt ZZ/ZZ08_.txt
ZZ/ZZ09_.txt ZZ/ZZ10_.txt
答案3
欢迎来到论坛,Zica!
我想建议organize
- 如果您有耐心,您可以创建一个脚本,yaml
可以在给定位置搜索文件、重命名、移动、排序,凡是您能想到的!我自己用的。我不知道你对 Linux 的熟练程度,但是 Git 有一个 readthedocs,它以一种非常容易理解的方式解释了你需要的一切。