2016-01-05 31 views
2

我有一個需要排序的全部271,568個文件的集合,全部在同一目錄中。幸運的是,他們都方便地命名的基礎上,他們應該在哪個文件夾基於文件名排序271,568文件在Bash中

例如,文件的一小部分可能看起來像:

. 
├── file.sort.shamwow 
├── file.sort.shamwow.abc 
├── file.sort.shamwow.example.alsoafile 
├── file.sort.shamwow.example.file 
├── foo.bar 
├── foo.bar.a 
├── foo.bar.b 
├── foo.lel 
├── foo.wow.a.50 
└── foo.wow.b 

當他們完成後進行排序,他們應該看看像:

. 
├── file 
│   └── sort 
│    └── shamwow 
│     ├── example 
│     │   ├── file.sort.shamwow.example.alsoafile 
│     │   └── file.sort.shamwow.example.file 
│     ├── file.sort.shamwow 
│     └── file.sort.shamwow.abc 
└── foo 
    ├── bar 
    │   ├── foo.bar 
    │   ├── foo.bar.a 
    │   └── foo.bar.b 
    ├── foo.lel 
    └── wow 
     ├── foo.wow.a.50 
     └── foo.wow.b 

使文件foo.wow.a.50將放在目錄wow是目錄foo的內內,等所有文件。

我想要的程序會根據點在目錄中的位置對文件進行排序。但是,如果該文件夾中只有一個文件(例如foo/wow/a.50),則不會爲該文件創建新的文件夾。

現在,我的半功能腳本的樣子:

#!/bin/bash 
#organization for gigantic folder 

> foo.txt 

for f in *; do 
    d=${f:3} 
    d=${d%%.*} 
    d=${d%%.*} 
    echo $d 

    if grep -Fxq "$d" foo.txt 
    then 
     mkdir -p $d 
     mv $f $d 
    else 
     echo $d >> foo.txt 
    fi 
done 

rm foo.txt 

但它並沒有真正的工作都順利。

有人可以修復我的代碼,或使自己的排序這混亂?謝謝!

+1

我建議服用'ls'參考出來的你的問題 - 它會讓你得到一堆到http://mywiki.wooledge.org/ParsingLs的鏈接,而你的問題實際上並不需要使用任何'ls'。 –

+0

@CharlesDuffy感謝您的建議。我將它改爲「根據文件名對Bash中的271,568個文件進行排序」。 –

+1

順便說一句,你不能有三個*文件*名爲'foo/bar','foo/bar/a'和'foo/bar/b',後兩者的目錄名將與文件名衝突前任的。 –

回答

0

忽略了你的請求的輸出是不可能的代表對文件系統(需要相同的名稱來指代既是文件和目錄):

#!/bin/bash 
#  ^^^^- must be bash shebang, must be shell 4.0 or newer 

# first pass: count directory references 
declare -A refcounts=() 
for f in *; do 
    f_part=$f 
    while [[ $f_part = *.* ]]; do 
    refcounts[$f_part]=$((${refcounts[$f_part]} + 1)) 
    f_part=${f_part%.*} 
    done 
    refcounts[$f_part]=$((${refcounts[$f_part]} + 1)) 
done 

# second pass: use that information 
# ...this is some ugly code, but I don't have the time right now to make it simpler. 
for f in *; do 
    f_part=${f%%.*} 
    f_rest=${f#*.} 
    while : "f=$f; f_part=$f_part; f_rest=$f_rest"; do 
    new_piece=${f_rest%%.*} 
    [[ $new_piece ]] || break 
    f_part_next=${f_part}.$new_piece 
    f_rest_next=${f_rest#"$new_piece"}; f_rest_next=${f_rest_next#.} 
    if [[ $f_rest = *.* ]] && ((${refcounts[${f_part_next}]:-0} > 1)); then 
     f_part=$f_part_next 
     f_rest=$f_rest_next 
    else 
     break 
    fi 
    done 
    dest="${f_part//"."/"/"}/${f_rest}" 
    mkdir -p -- "${dest%/*}" 
    mv -- "$f" "$dest" 
done 
+0

謝謝。我明天會試試這個。 –

+0

有很多mkdir和mv錯誤。它一半工作。我認爲我認爲我錯誤傳達的一個問題是程序不需要重命名文件。這可能會使它工作。 –

+0

對你的問題所做的修改使得這個回答非常無效。正如開篇所說,它試圖做你最初要求的不可能的事情 - 所以當然*它預計會失敗。 :) –