Files

排序和復製文件

  • June 16, 2021

我是新手,請耐心等待。

我有一個包含數千個文件的目錄。文件名總是以 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

這可以實現嗎?

謝謝!

循環遍歷文件集。選擇字母前綴。創建目錄(如有必要)並將文件移動到其中。

#!/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前綴mkdirmv當你高興時,它會做你想做的事。

使用perl 實用程序(在某些 linux 發行版上rename又名prename, file-rename) :perl-rename

rename  -n  'if (m/^(\w{1,2}?)(\d{2,}_.*)/) {mkdir $1; $_ = "$1/$1$2"}' *

注意:這適用於基於 perl 的重命名實用程序。rename -V您可以通過執行(或prename -Vfile-rename -V或)檢查是否安裝了它perl-rename -V。如果這提到 perl 或File::Rename,那麼它是 perl 版本的rename. 否則,它可能具有完全不同rename且不兼容的功能和命令行選項。這不適用於 util-linux 的重命名(或任何其他版本的重命名 - 它需要perl 重命名)util-linux

這使用每個匹配文件名的前一個或兩個“單詞”字元(非貪婪匹配)作為目錄,然後創建目錄,並將文件重命名為目錄。“單詞”字元 ( \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

引用自:https://unix.stackexchange.com/questions/650265