2014-09-04 44 views
0

我需要基於另一個文件夾(原始文件夾)及其子目錄的文件夾的子目錄重命名文件只有在正則表達式目錄重命名文件只有...比較和使用基於原來的文件夾

Folder1包含正確的文件名,因此如果folder2下的某個子目錄中的文件與folder1(原始文件)存在於相同的位置,它將被重命名爲原始文件。

例子:

. 
├── folder1 
│   ├── Somedir 
│   │   ├── file.xml 
│   │   ├── doc 
│   │   │   ├── CHANGELOG 
│   │   │   ├── TEST 
│   │   │   ├── file_test.txt 
│   │   │   ├── sample 
│   │   │   ├── README 
│   │   │   ├── mydir 
│   │   │   │   ├── exploitation-file.rst 
│   │   │   │   ├── advanced-file.txt 


. 
├── folder2 
│   ├── Somedir 
│   │   ├── file.xml 
│   │   ├── doc 
│   │   │   ├── CHANGELOG 
│   │   │   ├── TEST 
│   │   │   ├── filetest.txt 
│   │   │   ├── sample 
│   │   │   ├── README 
│   │   │   ├── mydir 
│   │   │   │   ├── exploitationfile.rst 
│   │   │   │   ├── advancedfile.txt 

運行後,「差異-qr /資料夾/文件夾2」我得到了這兩個文件夾之間的差異是這種情況是:

/folder2/somedir/filetest.txt (missing underscore) vs /folder1/somedir/file_test.txt 

/folder2/somedir/doc/mydir/exploitation-file.rst (missing hyphen) vs /folder1/somedir/doc/mydir/exploitation-file.rst 

/folder2/somedir/doc/mydir/advanced-file.txt (missing hyphen) vs /folder1/somedir/doc/mydir/advanced-file.txt 
+0

當我被錯誤刪除下劃線和連字符中的每個文件名執行腳本這個問題發生。 – saad 2014-09-04 10:40:19

+0

「folder1」是原來的文件夾,是我幾周前做過的舊備份。 – saad 2014-09-04 10:44:35

+0

應在哪些條件下重命名文件? folder1/file_name.ext在folder2中有filename.ext,所以如果有任何文件與'_'中的folder1相同?在這種情況下,對於folder1/fi_lename.ext或folder1/file_name.ext_? – NeronLeVelu 2014-09-04 11:14:14

回答

1

我會建議的Path::ClassPath::Class::Rule的組合。

創建這樣的問題的解決方案最困難的部分是測試它。因此,我提供了一個完全獨立的腳本,它基於您提供的示例結構創建測試環境。

此腳本基本上掃描__DATA__部分的文件和目錄以創建一個特殊的測試目錄。然後,代碼的後續部分實際上基於folder1中的信息修復了folder2目錄。

請注意,這將需要安裝上述兩個cpan模塊及其依賴關係。

use strict; 
use warnings; 
use autodie; 

use Path::Class; 
use Path::Class::Rule; 

my $testdir = dir('testing'); 

# Setup Testing Environment 
$testdir->rmtree(); 
$testdir->mkpath(); 
chdir($testdir); 

while (<DATA>) { 
    my ($type, $name) = split; 

    if ($type eq 'd') { 
     dir($name)->mkpath(); 
    } else { 
     file($name)->spew($name); 
    } 
} 

# Actual Solution 
my $backup_dir = dir('folder1'); 
my $main_dir = dir('folder2'); 

my $next = Path::Class::Rule->new->file->name(qr{[_-]})->iter($backup_dir); 

while (my $file = $next->()) { 
    my $correct_name = $file->basename(); 
    (my $stripped_name = $correct_name) =~ s{[_-]}{}g; 

    my $from_file = file($main_dir, $file->dir->relative($backup_dir), $stripped_name); 
    my $to_file = file($main_dir, $file->dir->relative($backup_dir), $correct_name); 

    if (-e $from_file) { 
     print "$from_file -> $to_file\n"; 
     $from_file->move_to($to_file); 
    } 
} 

__DATA__ 
d folder1 
d folder1/Somedir 
f folder1/Somedir/file.xml 
d folder1/Somedir/doc 
f folder1/Somedir/doc/CHANGELOG 
f folder1/Somedir/doc/TEST 
f folder1/Somedir/doc/file_test.txt 
f folder1/Somedir/doc/sample 
f folder1/Somedir/doc/README 
d folder1/Somedir/doc/mydir 
f folder1/Somedir/doc/mydir/exploitation-file.rst 
f folder1/Somedir/doc/mydir/advanced-file.txt 
d folder2 
d folder2/Somedir 
f folder2/Somedir/file.xml 
d folder2/Somedir/doc 
f folder2/Somedir/doc/CHANGELOG 
f folder2/Somedir/doc/TEST 
f folder2/Somedir/doc/filetest.txt 
f folder2/Somedir/doc/sample 
f folder2/Somedir/doc/README 
d folder2/Somedir/doc/mydir 
f folder2/Somedir/doc/mydir/exploitationfile.rst 
f folder2/Somedir/doc/mydir/advancedfile.txt 

輸出:

folder2/Somedir/doc/filetest.txt -> folder2/Somedir/doc/file_test.txt 
folder2/Somedir/doc/mydir/advancedfile.txt -> folder2/Somedir/doc/mydir/advanced-file.txt 
folder2/Somedir/doc/mydir/exploitationfile.rst -> folder2/Somedir/doc/mydir/exploitation-file.rst 
+0

聽起來不錯,但是如何在腳本中發送「ls」輸出到腳本而不包括文件列表(_DATA_)? – saad 2014-09-04 22:25:50

+0

沒有必要在DATA塊中包含任何信息。這僅用於測試目的。您只需使用標有'Actual Solution'的代碼部分並適當地設置您的backup_dir和main_dir。 – Miller 2014-09-04 22:33:52

+0

我建議您將此解決方案按原樣運行。試圖瞭解它在做什麼。然後它應該非常清楚如何適應你的實際情況。 – Miller 2014-09-04 22:34:44

1

可以使用一般的策略在「Better way to rename files based on multiple patterns」詳細其中打破了更名工作分三個階段:

job_select | job_strategy | job_process 

其中job_select負責選擇工作對象,job_strategy爲這些對象準備處理計劃,並最終執行計劃job_process

# job_select SRCDIR 
# Find all files having a dash or a hyphen in name 
job_select() 
{ 
    (cd "$1" && find . -type f -name '*[-_]*') 
} 

# job_strategy 
# Compute the renaming plan 
# 
# This assume that wrong names are deduced from good names by removing `_` and `-`. 
# The output has three columns, 
# 
# reldir|goodname|badname 
# 
# For instance, ./somedir/file_test.txt yields the plan 
# 
# ./somedir|file_test.txt|filestest.txt 
job_strategy() 
{ 
    sed -e ' 
    [email protected]/\([^/]*\)$/@|\[email protected] 
    h 
    [email protected]^.*|@@ 
    [email protected][-_]@@g 
    x 
    G 
    s/\n/|/ 
    ' 
} 

# job_process TGTDIR 
{ 
    cd "$1" || exit 
    IFS='|' 
    while read reldir goodname badname; do 
    relgoodname="$reldir/$goodname" 
    relbadname="$reldir/$badname" 
    if [ -r "$relbadname" ]; then 
     printf 'Rename %s to %s\n' "$relbadname" "$relgoodname" 
     mv "$relbadname" "$relgoodname" 
    else 
     printf 'Skip %s\n' "$relbadname" 
    fi 
    done 
} 

job_select /folder1 | job_strategy | job_process /folder2 
+0

我應該怎麼稱呼這個腳本,有些事情是這樣的? #。/ job_select.sh/folder1 | job_strategy | job_process/folder2 – saad 2014-09-04 13:12:17

+0

將內容粘貼到文件'job_rename.sh'中並將其作爲'sh job_rename調用。sh' - 一定要抓住最後一行,這不會顯示在我的瀏覽器中(我得到一個滾動條)!在運行腳本之前,請確保備份並註釋掉'mv'命令,這會讓您有機會審查將要執行的操作並驗證它是否符合您的期望。 – 2014-09-04 13:15:41

+0

我得到了這個輸出「Skip/badname」我該如何設置dir1和dir2!如果我運行這個腳本,它會修復基於dir1(原始目錄)的所有文件名? – saad 2014-09-04 13:24:48