rs1302
Anmeldungsdatum: 4. Februar 2016
Beiträge: Zähle...
|
Hallo,
ich suche einen Shell Befehl für eine SSH Session auf nein QNAP NAS, der mir:
a) alle Bilddateien b) alle Dateien
aus einem Ordner inklusive aller Unterordner
in einen Zielordner zB an die Freigabe "/Bilder/" verschiebt und doppelte Dateien auslässt bzw. übergeht. anders gesagt: Alle Bilder eines Verzeichnisbaums an eine neue Position verschieben und doppelte auslassen.
|
redknight
Moderator & Supporter
Anmeldungsdatum: 30. Oktober 2008
Beiträge: 21668
|
Hört sich wie ein Job für rsync an
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17432
|
Sind doppelte Bilder über den Namen identifizierbar oder können 2 gleichnamige Dateien unterschiedlich sein, aber 2 unterschiedlich benannte auch gleich?
|
rs1302
(Themenstarter)
Anmeldungsdatum: 4. Februar 2016
Beiträge: 57
|
Die Bilder werden nur über den Namen identifiziert.
Also ein Bild ist "doppelt" wenn der Name ident ist. In meiner Fotosammlung haben sich zahllose Ordner und Unterordner angesammelt. Viele Bilder sind doppelt vorhanden. Zb in einem Ordner "ausarbeiten" oder "4Oma" usw...
Ich habe mit dem ExifTool alle Bilder anhand ihres Aufnahmedatums umbenannt. Demnach haben doppelte Bilder auch gleiche Namen.
Jetzt möchte ich alle Bilder in ein neues Verzeichnis verschieben. Damit möchte ich die überflüssigen Ordner und doppelten Bilder eliminieren.
Im "alten" Bilder Verzeichnis soll die Ordnerstruktur mit allen doppelten Bildern erhalten bleiben. Diese kann ich bei bedarf nachträglich händisch überprüfen.
Erster Schritt wäre mal das Verschieben
|
rs1302
(Themenstarter)
Anmeldungsdatum: 4. Februar 2016
Beiträge: 57
|
ich dachte an folgende Befehle:
Jedoch bin ich mir nicht sicher, was mit doppelten Files passiert. Ich glaube, dass alle Bilder (JPGs) verschoben werden und doppelte Namen überschrieben würden jeweils aus dem Stammverzeichnis meiner Bildersammlung: find . -name '*.jpg' -exec mv [] /Pictures/ \;
oder:
mv **/*.jpg /Pictures/
|
wxpte
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1004
|
Grundsätzlich sollte das gehen, drei Anmerkungen habe ich aber:
im find-Befehl müssen geschweifte Klammern verwendet werden: find . -name '*.jpg' -exec mv {} /Pictures/ \; befindet sich das Zielverzeichnis tatsächlich direkt unterhalb des Rootverzeichnissses? ich bin mir nicht sicher, ob der Ausdruck **/*.jpg wie von dir gewünscht funktioniert. Besser ist find .
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10978
|
wxpte schrieb: ich bin mir nicht sicher, ob der Ausdruck **/*.jpg wie von dir gewünscht funktioniert. Besser ist find .
Wenn man die Bash als Shell nutzt, muss man dafür die globstar-Option setzen: http://shellrunner.com/better-simpler-searching-and-scripting-with-bash-globstar/
|
wxpte
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1004
|
Das war mir so auch noch nicht bekannt, danke für den Tipp. 👍
|
rs1302
(Themenstarter)
Anmeldungsdatum: 4. Februar 2016
Beiträge: 57
|
Durch den "find" Befehl werden zwar alle Bilder gefunden, diese werden jedoch restlos verschoben und im Zielverzeichnis überschrieben.
Ich möchte doppelte Daten jedoch im Quellverzeichnis erhalten! "mv" hat keine mir bekannte Option um bestehende Daten zu überspringen oder übergehen.
Ich bräuchte also eine Art {} Existenz if Prüfung welche mv nur ausführt falls {} nicht vorhanden ist.
Oder einen anderen Befehl, der "übergehen" als Option anbietet.
Ein sh Skript könnte dies vielleicht erledigen.
Die sh Shell ist am QnapNAS vorhanden. Ein Skript müsste folgende Befehle abarbeiten:
1.#!/bin/sh 2.Find "alle "$X" = jpg und jepg in /xy/Quelle/; 3.Prüfe ob "$X" in /xy/Ziel/ vorhanden ist; 4.If:
4a.nein: mv File {} Quelle Ziel;
4b.ja: break; Wie realisiere ich Nr3?
Muss ich für die Existenzprüfung auch den find Befehl einsetzen und dem Ergebnis eine 2te Variable "$Y" zuordnen, welche ich dann mit " if $X == $Y { mv Quelle Ziel};" prüfe? Wie könnte solch ein Skript tatsächlich aussehen?
|
wxpte
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1004
|
rs1302 schrieb: Ich bräuchte also eine Art {} Existenz if Prüfung welche mv nur ausführt falls {} nicht vorhanden ist.
Wie wäre es mit
| #!/bin/bash
while read d
do
if [ ! -e /Pictures/$(basename $d) ]
then
mv $d /Pictures/
fi
done< <(find . -name '*.jpg')
|
❓ Erklärung: Zeile 6 wird nur ausgeführt, wenn die Datei im Zielverzeichnis nicht existiert. Dein Punkt 4b. wird also nicht benötigt. ▶ If-Bedingungen ▶ Kommando-Schleife
|
rs1302
(Themenstarter)
Anmeldungsdatum: 4. Februar 2016
Beiträge: 57
|
Danke.
Ich hoffe mein QnapNas hat neben "sh" auch "bash".
Werde ich testen sobald ich zu Hause bin.
Das Skript liest alle Daten " Read d"
Ich gehe davon aus, dass das Skript im bilder-Wurzelverzeichnis zu starten ist und read den ganzen Baum "durchliest".
Wenn ! ( nicht) verfügbar dann verschieben... genau das was ich wollte!
"basename" kannte ich nicht, werde ich nachlesen.
Klar, bei while, kommt die Bedingung hinterher...
Soweit verstehe ich das Skript.
Danke, werde es testen und feedback geben. Eine Frage noch:
Das qnap NAS bietet immer 2 Optionen:
Zb:
"Verschieben und überschreiben" oder "verschieben und übergehen".
Ich dachte es gibt einen einfachen mv Befehl der diesen "Schalter" optional bietet.
Der Fall " verschieben und nicht überschreiben" kommt doch permanent vor.
Verwunderlich das es dafür keinen eigenen Schalter gibt.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
|
wxpte schrieb: | #!/bin/bash
while read d
do
if [ ! -e /Pictures/$(basename $d) ]
then
mv $d /Pictures/
fi
done< <(find . -name '*.jpg')
|
❓
wxpte: Eine Bitte: bei solchen Codevorschlägen achte doch bitte auf ein paar handwerkliche Grundregeln:
Sauberes "$Quoting" ist ein must, sonst zerschießt das 1. Leerzeichen das Skript, und der arme Hilfesuchende weiß gar nicht warum. Sowas wie find kann man nicht parsen ! - bitte verbreite solche unsicheren Vorschläge nicht hier auf dem Forum. Eine solide Alternative wäre ein find .... -exec bash -c '[Dein_Code]' {} \; Eine vernünftige Einrückung (4 oder 8 Spalten pro Ebene) ist kein Hexenwerk, und erleichtert den Überblick über Dein Skript enorm:
| #!/bin/bash
find . -name '*.jpg' -exec bash -c '
for d; do
if [ ! -e "/Pictures/$(basename "$d")" ] ; then
mv "$d" /Pictures/
fi
done
' {} +
|
Ich hoffe jetzt nur, dass ich da keine Tippfehler drin habe. - ich habe diesen Code nämlich nicht nochmal getestet ! LG, track
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17432
|
rs1302 schrieb: Ein Skript müsste folgende Befehle abarbeiten:
#!/bin/sh
Find "alle "$X" = jpg und jepg in /xy/Quelle/;
Prüfe ob "$X" in /xy/Ziel/ vorhanden ist;
If:
nein: mv File {} Quelle Ziel;
ja: break;
Wie realisiere ich Nr3?
Ich glaube Ihr habt die Frage nicht richtig verstanden. Er sucht in a mit allen Unterverzeichnissen und will verschieben nach e, wo die Dateien in ein analoges Geäst fallen sollen, außer sie sind dort schon irgendwo. Also
| a/b/c/foo.jpg
a/b/d/foo.jpg
a/b/d/bar.jpg
|
soll zu
| e/b/c/foo.jpg
e/b/d/bar.jpg
|
oder
| e/b/d/foo.jpg
e/b/d/bar.jpg
|
werden.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17432
|
Wenn Du zuvor die Verzeichnisstruktur kopierst:
| t201:~/proj/mini/forum/test > tree a b
a
└── b
└── c
b
├── bar
├── c
│ ├── daz
│ └── foo
└── foo
3 directories, 4 files
|
Dann kannst Du dies machen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
t201:~/proj/mini/forum/test > find b -type f -exec ./schonda.sh {} ";"
schon da: b/foo
t201:~/proj/mini/forum/test > tree a b
a
└── b
├── bar
└── c
├── daz
└── foo
b
├── c
└── foo
3 directories, 4 files
|
wobei schonda.sh so aussieht:
| #!/bin/bash
#
gesucht=$(basename "$1")
res=$(find a -name "$gesucht")
test -z $res && mv $1 a/$1 || echo "schon da: $1"
|
|
wxpte
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1004
|
Hallo track, 1) da hast du natürlich Recht, mein Fehler 2) Das wäre einmal eine sinnvolle Ergänzung des Bash-Skripting-Guide für Anfänger. In dem ganzen Artikel finde ich den Begriff "parsen" nicht ein einziges Mal. Eine Übersicht, worauf man diesbezüglich achten muss, wäre gerade für Anfänger sehr wichtig. Besonders, wenn es sich, wie du schreibst, um Grundregeln handelt.
|