2017-09-21 6 views
0

ich ein Problem mit dem folgenden Shell-Skript bin vor:Shell-Skript: Finden Sie nicht mit Ordnern in Anführungszeichen umgehen

#!/bin/bash 

searchPattern=".*\/.*\.abc|.*\/.*\.xyz|.*\/.*\.[0-9]{3}" 
subFolders=$(find -E * -type d -regex ".*201[0-4][0-1][0-9].*|.*20150[1-6].*" -maxdepth 0 | sed 's/.*/"&"/') 

echo "subFolders: $subFolders" 

# iterate through subfolders 
for thisFolder in $subFolders 
do 
    echo "The current subfolder is: $thisFolder" 

    find -E $thisFolder -type f -iregex $searchPattern -maxdepth 1 -print0 | xargs -0 7z a -mx=9 -uz1 -x!.DS_Store ${thisFolder}/${thisFolder}_data.7z 
done 

Die Idee dahinter ist, Dateitypen mit der Endung .abc, .xyz zu archivieren und zu. 000-.999 in einem 7z-Archiv pro Unterordner. Ich kann jedoch nicht mit Ordnern einschließlich Leerzeichen umgehen. Als ich das Skript ausführen, wie oben gezeigt ich folgende Fehlermeldung immer erhalten:

find: "20130117_test": No such file or directory 

Wenn ich das Skript mit der Linie

subFolders=$(find -E * -type d -regex ".*201[0-4][0-1][0-9].*|.*20150[1-6].*" -maxdepth 0 | sed 's/.*/"&"/') 

geändert

subFolders=$(find -E * -type d -regex ".*201[0-4][0-1][0-9].*|.*20150[1-6].*" -maxdepth 0) 

das Skript arbeitet laufen wie Charme, aber natürlich nicht für Ordner mit Platz.

Merkwürdigerweise, wenn ich die folgende Zeile direkt in der Schale ausführen, funktioniert es wie erwartet:

find -E "20130117_test" -type f -iregex ".*\/.*\.abc|.*\/.*\.xyz|.*\/.*\.[0-9]{3}" -maxdepth 1 -print0 | xargs -0 7z a -mx=9 -uz1 -x!.DS_Store "20130117_test"/"20130117_test"_data.7z 

Ich weiß, das Problem irgendwie zum Speichern einer Liste von Ordnern (in Anführungszeichen) in der Beziehung steht SubFolders-Variable, aber ich finde einfach keinen Weg, um es richtig funktionieren zu lassen.

Ich hoffe, jemand weiter fortgeschritten in der Schale hier kann mir helfen.

+0

Der normale Weg zur Schleife am Ausgang (GNU) 'find' ist:' während IFS = -r -d 'gelesen ' Dateiname; mach etwas mit "$ filename" ...; done <<(find .... -print0) '. Siehe [ParsingLs] (http://mywiki.wooledge.org/ParsingLs) (Ich denke, es ist eine gute Idee, wenn Sie diese Seite lesen, und vielleicht lesen Sie alle Informationen auf dieser Seite!). –

+0

@gniourf_gniourf danke für den Hinweis! Es hat mich ganz etwas studieren, aber ich schaffte es zum Laufen zu bringen – zionlion

+0

Wörtliche Zitate (Quotes in den Daten Skript Prozesse) (meine Antwort siehe unten) kann für syntaktische Anführungszeichen (Anführungszeichen im Skript selbst) nicht ersetzen. Siehe [BashFAQ # 50] (http://mywiki.wooledge.org/BashFAQ/050). –

Antwort

1

Im Allgemeinen sollten Sie nicht find in einem Versuch verwenden, um eine Liste der Dateinamen zu generieren. Sie können eine zitierte Liste nicht so erstellen, wie Sie es versuchen; Es gibt einen Unterschied zwischen den Anführungszeichen in einen Parameterwert und um eine Parametererweiterung. Gerade hier können Sie nur einfache Muster verwenden:

shopt -s nullglob 

subFolders=(
    *201[0-4][0-1][0-9]* 
    *20150[1-6]* 
) 
for thisFolder in "${subFolders[@]}"; do 
    echo "The current subfolder is: $thisFolder" 
    to_archive=(
    */*.abc 
    */*.xyz 
    */*.[0-9][0-9][0-9] 
) 
    7z a -mx9 -uz1 -x!.DS_Store "$thisFolder/$thisFolder_data.7z" "${to_archive[@]}" 
done 
+0

danke für den Vorschlag. Wenn ich jedoch einfach folgendes versuche: 'subFolders = (* 201 [0-4] [0-1] [0-9] * * 20150 [1-6] *); für thisFolder in "$ {subFolders [@]}"; machen; echo "Der aktuelle Unterordner ist: $ thisFolder"; done', ich komme immer noch nicht gut mit Leerzeichen zurecht, da ich 'den aktuellen Unterordner bekommen habe: 20130208_test Der aktuelle Unterordner ist: 20130208_test mit Leerzeichen' und außerdem bekomme ich' Der aktuelle Unterordner ist: * 20150 [1-6] * '. Hast du eine Idee, was könnte das Problem sein? – zionlion

+1

Das sieht so aus, als ob es sich mit Räumen genau so verhält, wie es sollte. Was das zweite Problem angeht, gibt es keine Ordner, die mit '* 20150 [1-6] *' übereinstimmen; Verwenden Sie 'shopt -s nullglob', damit nicht übereinstimmende Muster ignoriert und nicht als Literalstrings verwendet werden. – chepner

+0

die 'shopt -s nullglob'option macht Sinn, weil ich in meinem Testordner eigentlich keine Unterordner habe, die mit etwas wie' * 20150 [1-6] * 'beginnen. Auch Räume werden jetzt gut behandelt. Mir ist gerade aufgefallen, dass aus früheren Tests ein falscher Ordner erstellt wurde ("20130208_test" sollte nicht existieren, sondern nur "20130208_test mit Leerzeichen"). Im Moment sind jedoch nicht nur Verzeichnisse, sondern auch Dateien in "subFolders" aufgelistet. Wie kann ich nur Ordner in Unterordner aufnehmen? – zionlion

0

die Eingabe von gniourf_gniourf und chepner Kombination konnte ich den folgenden Code produzieren, das ist genau das tut, was ich will.

#!/bin/bash 

shopt -s nullglob 

find -E "$PWD" -type d -maxdepth 1 -regex ".*201[0-5][0-1][0-9].*" -print0 | while IFS="" read -r -d "" thisFolder ; do 
    echo "The current folder is: $thisFolder" 
    to_archive=("$thisFolder"/*.[Aa][Bb][Cc] "$thisFolder"/*.[Xx][Yy][Zz] "$thisFolder"/*.[0-9][0-9][0-9]) 

    if [ ${#to_archive[@]} != 0 ] 
    then 
    7z a -mx=9 -uz1 -x!.DS_Store "$thisFolder"/"${thisFolder##*/}"_data.7z "${to_archive[@]}" && rm "${to_archive[@]}" 
    fi 
done 

shopt -s nullglob führt zu Ignoranz gegenüber nicht passenden Zeichen

find... Suchen für die Verzeichnisse RegexMuster passenden und Ströme jeweils passenden Ordner der while-Schleife der Null-Separator verwendet wird.

innerhalb der while-Schleife ich die $thisFolder variable Expansion sicher zitieren kann und daher mit möglichen Räumen befassen.

mit absoluten Pfade anstelle von relativen Pfaden 7z keine Ordner im Archiv erstellen anweist

Verwandte Themen