2017-03-05 5 views
0

So habe ich mehrere Dateien in bash in einem Verzeichnis namens songs_old. Ich möchte sie in einen Ordner namens Songs mit einem anderen Namen kopieren. Einige Namen der Eingabedateien enthalten:Bulk kopieren und benennen Sie mehrere Dateien in Bash, mit Unterstrichen

unknownsong_song152.mid 
town_song154.mid 
nm_battle_song158.mid 
fanfare_song159.mid 

ich die Ergebnisse in "Songs" sein wollen wie:

song152_unknownsong.mid 
song154_town.mid 
song158_nm_battle.mid 
song159_fanfare.mid 

ich den folgenden Code versucht, die Dateien zu kopieren:

#!/bin/bash 
for i in "./songs_old/"*".mid";do mkdir -p "./songs" 
    cp "$i" "./songs/`basename "${i%.*}" | cut -d'_' -f2`_`basename "${i%.*}" | cut -d'_' -f1`.mid" 
done 

Und meine Ergebnisse waren wie folgt:

song152_unknownsong.mid 
song154_town.mid 
battle_nm.mid 
song159_fanfare.mid 

Wie kann ich die Dateien mit den gewünschten Ergebnissen kopieren?

Antwort

1

Ihr cp Befehl wird an geleitet - das ist das Problem. Sie können die Schleife auf diese Weise umschreiben:

#!/bin/bash 
mkdir -p songs 
cd songs_old 
for i in *.mid; do 
    [[ -f "$i" ]] || continue # make sure we have a file 
    new_file=$(sed -E 's/^(.*)_(song[0-9]+).mid$/\2_\1.mid/' <<< "$i") 
    echo "Copying $i to $new_file" 
    cp "$i" "../songs/$new_file" 
done 
  • mehr Sinn macht, die „Lieder“ Verzeichnis nur einmal
  • von wechseln mit cd songs_old und Globbing zu schaffen, beseitigen wir die Notwendigkeit für basename
  • verwenden sed und einen regulären Ausdruck den neuen Namen
  • Verwendung ../songs relativen Pfad zu erstellen, während das Kopieren

Für Ihre Gruppe von Dateien, gibt es diese Ausgabe:

Copying fanfare_song159.mid to song159_fanfare.mid 
Copying nm_battle_song158.mid to song158_nm_battle.mid 
Copying town_song154.mid to song154_town.mid 
Copying unknownsong_song152.mid to song152_unknownsong.mid 
2

reine bash Regex verwenden, können Sie dies tun:

cd songs_old 
mkdir -p ../songs 

for f in *.mid; do 
    [[ $f =~ ^(.+)_([^_]+)(\.[^.]+)$ ]] && 
     cp "$f" ../songs/"${BASH_REMATCH[2]}_${BASH_REMATCH[1]}${BASH_REMATCH[3]}" 
done 

Dies wird folgende cp Befehle für bestimmte Probe laufen:

cp unknownsong_song152.mid ../songs/song152_unknownsong.mid 
cp town_song154.mid ../songs/song154_town.mid 
cp nm_battle_song158.mid ../songs/song158_nm_battle.mid 
cp fanfare_song159.mid ../songs/song159_fanfare.mid 
+1

Danke, ich merke meinen Fehler :) – anubhava

Verwandte Themen