ubuntuusers.de

Find - Vorhandene Dateien verschieben problem

Status: Ungelöst | Ubuntu-Version: Ubuntu Budgie 22.04 (Jammy Jellyfish)
Antworten |

DPoi

Avatar von DPoi

Anmeldungsdatum:
6. Januar 2015

Beiträge: 356

Hallo Leute, ich habe folgendes vor. Ich besitze viele Dateien die einen langen Dateinamen mit passenden Inhalten haben. Das sind PDFs, Bilder und Videos. Diese möchte ich "vorsortieren" um sie dann schneller bearbeiten zu können.

Ich habe hier im Forum ein script gefunden das eigentlich genau das macht was es soll:

1
find . -type f -iname '*namansteil*' -exec sh -c 'ziel="namensteil/${0#./}"; mkdir -p "${ziel%/*}"; mv "$0" "$ziel"' {} \;

Es funktioniert solange noch KEIN Unterverzeichnis mit der Bezeichnung "namensteil" existiert "mkdir -p". Existriert es aber dann wird darin noch einmal ein Unterverzeichnis mit gleichem Namen erstellt. Und genau das möchte ich verhindern. Existiert dieses, dann soll es auch benutzt werden. Alles was mir hier so eingefallen ist funktioeniert nicht. Bin da auch kein Script-Profi.

Kann man das auch eleganter lösen?

Danke und Gruß!

Dogeater

Anmeldungsdatum:
16. Juni 2015

Beiträge: 3381

Ohne dein Script zu testen.. so könnte es gehen:

find . -type f -iname '*namansteil*' -exec sh -c 'ziel="../namensteil/${0#./}"; mkdir -p "${ziel%/*}"; mv "$0" "$ziel"' {} \;

karzer Team-Icon

Wikiteam
Avatar von karzer

Anmeldungsdatum:
10. April 2022

Beiträge: 1497

Wohnort: Bad Oeynhausen

Hallo,

vielleicht das mal versuchen:

1
find . -type f -iname '*title*' -exec sh -c 'ziel="title/${0#./}";if [ ! -d "${ziel%/*}" ]; then mkdir -p "${ziel%/*}" && mv "$0" "$ziel";else mv "$0" "$ziel";fi' {} \;

Hab's getestet.

DPoi

(Themenstarter)
Avatar von DPoi

Anmeldungsdatum:
6. Januar 2015

Beiträge: 356

Dogeater schrieb:

Ohne dein Script zu testen.. so könnte es gehen:

find . -type f -iname '*namansteil*' -exec sh -c 'ziel="../namensteil/${0#./}"; mkdir -p "${ziel%/*}"; mv "$0" "$ziel"' {} \;

nee... dann verschiebt er es (logischerweise) ein Verzeichnis höher aber baut dort immernoch Unterverzeichnisse mit gleichen Namen "$ziel".

Tx!

karzer Team-Icon

Wikiteam
Avatar von karzer

Anmeldungsdatum:
10. April 2022

Beiträge: 1497

Wohnort: Bad Oeynhausen

Hallo,

hast du meinen Vorschlag getestet?

DPoi

(Themenstarter)
Avatar von DPoi

Anmeldungsdatum:
6. Januar 2015

Beiträge: 356

karzer schrieb:

Hallo,

vielleicht das mal versuchen:

1
find . -type f -iname '*title*' -exec sh -c 'ziel="title/${0#./}";if [ ! -d "${ziel%/*}" ]; then mkdir -p "${ziel%/*}" && mv "$0" "$ziel";else mv "$0" "$ziel";fi' {} \;

Hab's getestet.

Auch nicht. Wenn das Ziel-Verzeichnis 'title' schon besteht dann haut er eines mit gleichem Namen in das Zielverzeichnis und verschiebt die Daten dorthin. Keine Verbesserung... hmmmm!

Ich bin der Meinung das "mkdir -p" macht da Probleme weil "kein Fehler, wenn vorhanden; übergeordnete Verzeichnisse erzeugen, wenn notwendig". Das bringt mich durcheinander. Man kann mkdir nicht ohne -p aufrufen wenn das Verzeichnis schon existiert.

Also muss bestimmt das Script so angepasst werden, das man zuvor schaut ob $ziel schon vorhanden ist, dann KEIN mkdir aufrufen sondern NUR die Daten verschieben. Mein Problem momentan, ich kann das (noch) nicht ins script umsetzen...

Tx!

DPoi

(Themenstarter)
Avatar von DPoi

Anmeldungsdatum:
6. Januar 2015

Beiträge: 356

Aber das if [ ! -d "${ziel%/*}" ]; then sollte doch das mkdir überspringen da es ja besteht. Richtig?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13131

DPoi schrieb:

Es funktioniert solange noch KEIN Unterverzeichnis mit der Bezeichnung "namensteil" existiert "mkdir -p". Existriert es aber dann wird darin noch einmal ein Unterverzeichnis mit gleichem Namen erstellt. Und genau das möchte ich verhindern. Existiert dieses, dann soll es auch benutzt werden. Alles was mir hier so eingefallen ist funktioeniert nicht. Bin da auch kein Script-Profi.

Wenn ich das richtig sehe, ist Dein Problem, dass Du das angelegte Verzeichnis ebenfalls durchsuchst und dann immer wieder ein neues Verzeichnis mit dem Namen anlegst. Wenn Du das Skript drei mal ausführst, solltest Du "namensteil/namensteil/namensteil" bekommen usw.

Zwei Lösungen:

  • Lege Dein Zielverzeichnis außerhalb des Verzeichnisses, das als Eingang dient. Das wäre meine bevorzugte Lösung, weil das sauberer und weniger fehleranfällig ist.

  • Definiere den Zielpfad anders - nämlich, indem Du nur den Basename nimmst.

  • Verhindere, dass Du in "namensteil" gehst, z.B. durch die Option -prune.

Ungetestet

Option 2

1
find -type f -iname '*namensteil*' -exec sh -ec 'ziel="namensteil/${0##./}"; mkdir -p "$(dirname "$ziel")"; [ -f "$ziel" ] || mv "$0" "$ziel"' {} \;

Option 3

1
find -type d -name namensteil -prune -o -type f -iname '*namensteil*' -exec sh -ec 'ziel="namensteil/${0#./}"; mkdir -p "${ziel%/*}"; mv "$0" "$ziel"' {} \;

karzer Team-Icon

Wikiteam
Avatar von karzer

Anmeldungsdatum:
10. April 2022

Beiträge: 1497

Wohnort: Bad Oeynhausen

DPoi schrieb:

karzer schrieb:

Hallo,

vielleicht das mal versuchen:

1
find . -type f -iname '*title*' -exec sh -c 'ziel="title/${0#./}";if [ ! -d "${ziel%/*}" ]; then mkdir -p "${ziel%/*}" && mv "$0" "$ziel";else mv "$0" "$ziel";fi' {} \;

Hab's getestet.

Auch nicht. Wenn das Ziel-Verzeichnis 'title' schon besteht dann haut er eines mit gleichem Namen in das Zielverzeichnis und verschiebt die Daten dorthin.

Das verstehe ich nicht. Bei mir funktioniert genau das einwandfrei.

user@penguin:~/temp$ ls
total 0
-rw-r--r-- 1 user user 0 Aug 19 19:53 1title.txt
-rw-r--r-- 1 user user 0 Aug 19 19:53 2title.txt
-rw-r--r-- 1 user user 0 Aug 19 19:53 title.txt
user@penguin:~/temp$ find . -type f -iname '*title*' -exec sh -c 'ziel="title/${0#./}";if [ ! -d "${ziel%/*}" ]; then mkdir -p "${ziel%/*}" && mv "$0" "$ziel";else mv "$0" "$ziel";fi' {} \;
user@penguin:~/temp$ ls
total 0
drwxr-xr-x 1 user user 58 Aug 19 19:59 title
user@penguin:~/temp$ ls title/
total 0
-rw-r--r-- 1 user user 0 Aug 19 19:53 1title.txt
-rw-r--r-- 1 user user 0 Aug 19 19:53 2title.txt
-rw-r--r-- 1 user user 0 Aug 19 19:53 title.txt
user@penguin:~/temp$

DPoi

(Themenstarter)
Avatar von DPoi

Anmeldungsdatum:
6. Januar 2015

Beiträge: 356

Booooooh... ich habe es! Jetzt scheint es zu funktionieren:

1
find . -maxdepth 1 -type f -iname '*title*' -exec sh -c 'ziel="title/${0#./}";if [ ! -d "${ziel%/*}" ]; then mkdir -p "${ziel%/*}" && mv "$0" "$ziel";else mv "$0" "$ziel";fi' {} \;

Das funktioniert!!

DPoi

(Themenstarter)
Avatar von DPoi

Anmeldungsdatum:
6. Januar 2015

Beiträge: 356

rklm schrieb:

Wenn ich das richtig sehe, ist Dein Problem, dass Du das angelegte Verzeichnis ebenfalls durchsuchst und dann immer wieder ein neues Verzeichnis mit dem Namen anlegst. Wenn Du das Skript drei mal ausführst, solltest Du "namensteil/namensteil/namensteil" bekommen usw.

Das wird es sein. Ich habe find mal mit -maxdepth 1 mitgeteilt das nur eine Verzeichnistiefe berücksichtigt werden soll. Das haut astrein hin... 😛

Danke!!!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13131

DPoi schrieb:

rklm schrieb:

Wenn ich das richtig sehe, ist Dein Problem, dass Du das angelegte Verzeichnis ebenfalls durchsuchst und dann immer wieder ein neues Verzeichnis mit dem Namen anlegst. Wenn Du das Skript drei mal ausführst, solltest Du "namensteil/namensteil/namensteil" bekommen usw.

Das wird es sein. Ich habe find mal mit -maxdepth 1 mitgeteilt das nur eine Verzeichnistiefe berücksichtigt werden soll. Das haut astrein hin... 😛

Wie, Du hast sowieso nur eine Ebene von Dateien? Dann braucht man find normalerweise nicht und die Sache wird deutlich einfacher.

karzer Team-Icon

Wikiteam
Avatar von karzer

Anmeldungsdatum:
10. April 2022

Beiträge: 1497

Wohnort: Bad Oeynhausen

Bspw. so:

1
2
3
4
5
6
search_arr=(titel test)
for operand in "${search_arr[@]}"; do 
      mkdir -p $operand 
      for file in ./*$operand*: 
           mv $file $operand/  
done 

Sucht in diesem Verzeichnis nach Dateien, die titel und test enthalten, erstellt gleichnamige Ordner und verschiebt die Dateien darein.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13131

karzer schrieb:

1
2
3
4
5
6
search_arr=(titel test)
for operand in "${search_arr[@]}"; do 
      mkdir -p $operand 
      for file in ./*$operand*: 
           mv $file $operand/  
done 

Ist die innere Schleife korrekte bash-Syntax? Man muss hier auch testen, dass $file wirklich eine Datei bezeichnet. Sonst wird nämlich auch das Verzeichnis "$operand" erfasst.

Sucht in diesem Verzeichnis nach Dateien, die titel und test enthalten, erstellt gleichnamige Ordner und verschiebt die Dateien darein.

Man braucht da kein Array und damit auch keine bash:

1
2
3
4
5
6
7
for operand in titel test; do 
  mkdir -p "$operand"

  for file in *"$operand"*; do 
    [ -f "$file" ] && mv "$file" "$operand"
  done
done

karzer Team-Icon

Wikiteam
Avatar von karzer

Anmeldungsdatum:
10. April 2022

Beiträge: 1497

Wohnort: Bad Oeynhausen

rklm schrieb:

Ist die innere Schleife korrekte bash-Syntax? Man muss hier auch testen, dass $file wirklich eine Datei bezeichnet. Sonst wird nämlich auch das Verzeichnis "$operand" erfasst.

Das ist richtig, ich hatte das nicht mit Verzeichnissen ausprobiert.

Man braucht da kein Array und damit auch keine bash:

Einen array würde ich auch nur verwenden, wenn man eine größere Menge Suchstrings benutzen will. Sonst ist deine Lösung natürlich praktischer.

Antworten |