2016-08-04 10 views
1

Ich habe die folgende Verzeichnisstruktur:separate Ordner in Unterordner nach in bash Nummerierung

1_loc 
2_buzdfg 
4_foodga 
5_bardfg 
6_loc 
8_buzass 
9_foossd 
12_bardaf 

Es Zahlen im Ordner Bestellung fehlen.

Ich mag diese Ordner in Unterordner trennen nach ihren Zahlen, so dass alle Ordner mit einer Nummer kleiner als 6 (vor den zweiten _loc Ordnern) folder1 und alle Ordner mit einer Reihe gehen würden, gleich oder größer als 6 mit gehe zu folder2.

Ich kann das Problem natürlich sehr einfach mit der Maus lösen, aber ich wollte einen Vorschlag, wie man das automatisch vom Terminal aus macht.

Irgendwelche Ideen?

Antwort

2
while read -r line; do 
    # Regex match the beginning of the string for a character between 1 and 5 - change this as you'd please to any regex 
    FOLDERNUMBER="" 
    [[ "$line" ~= "^[1-5]" ]] && FOLDERNUMBER="1" || FOLDERNUMBER="2" 

    # So FOLDERPATH = "./folder1", if FOLDERNUMBER=1 
    FOLDERPATH="./folder$FOLDERNUMBER" 

    # Check folder exists, if not create it 
    [[ ! -d "$FOLDERPATH" ]] && mkdir "$FOLDERPATH" 

    # Finally, move the file to FOLDERPATH 
    mv "$line" "$FOLDERPATH/$(basename $line)" 
done < <(find . -type f) 
# This iterates through each line of the command in the brackets - in this case, each file path from the `find` command. 
+0

sehr gut gemacht und dokumentiert! – fedorqui

2

Ich denke, die Lösung besteht darin, die Dateien durchlaufen und überprüfen Sie die Nummer vor der ersten _.

Zum einen wollen wir prüfen, wie die Zahl vor _ erhalten:

$ d="1_loc_b" 
$ echo "${d%%_*}" 
1 

OK, so dass dies funktioniert. Dann lassen Sie uns Schleife:

for file in * 
do 
    echo "$file" 
    ((${file%%_*} > 5)) && echo "moving to dir2/" || echo "moving to dir1/" 
done 
+0

Warum brauche ich nicht '$' vor '(($ {file %% _ *}> 5))' '? Oder, warum muss ich nur '$' verwenden, wenn ich das Ergebnis wiedergeben möchte? – dangom

+0

@DanielG, weil dies das bedingte Konstrukt ['((...))'] verwendet (https://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs). – fedorqui

1

Angenommen folder1 und folder2 im selben Verzeichnis vorhanden ist, werde ich es tun, wie folgt:

for d in *_*; do # to avoid folder1 and folder2 
    # check if the first field seperated by _ is less than 5 
    if ((`echo $d | cut -d"_" -f1` < 6)); then 
     mv $d folder1/$d; 
    else 
     mv $d folder2/$d; 
    fi; 
done 

(mehr über cut)

1

können Sie Gehe in das aktuelle Verzeichnis und führe diese einfachen Befehle aus:

mv {1,2,3,4}_* folder1/ 
mv {5,6,7,8}_* folder2/ 

Dies setzt keine anderen Dateien/Verzeichnisse voraus, die mit diesen Präfixen beginnen (d. H. 1-8).

1

Eine weitere reine bash, Parameter-Erweiterungslösung: -

#!/bin/bash 

# 'find' returns folders having a '_' in their names, the flag -print0 option to 
# preserve special characters in names. 

# the folders are names as './1_folder', './2_folder', bash magic is done 
# to remove those special characters. 

# '-v' flag in 'mv' for verbose action 

while IFS= read -r -d '' folder; do 

    folderName="${folder%_*}"  # To strip the characters after the '_' 
    finalName="${folderName##*/}" # To strip the everything before '/' 

    ((finalName > 5)) && mv -v "$folder" folder1 || mv -v "$folder" folder2 

done < <(find . -maxdepth 1 -mindepth 1 -name "*_*" -type d -print0) 
1

Sie können die ein Skript mit dem folgenden Code erstellen und wenn Sie es ausführen, werden die Ordner beliebig bewegt werden ..

#seperate the folders into 2 folders 
#this is a generic solution for any folder that start with a number 
#!/bin/bash 
for file in * 
do 
prefix=`echo $file | awk 'BEGIN{FS="_"};{print $1}'` 

if [[ $prefix != ?(-)+([0-9]) ]] 
then continue 
fi 

if [ $prefix -le 4 ] 
then mv "$file" folder1 

elif [ $prefix -ge 5 ] 
then mv "$file" folder2 

fi 

done