Hallo. Ich brauche mal eine Idee: Gegeben sind Unterorder in denen sich Dateien befinden nach folgendem Aufbau: dir1\1.jpg -> a.jpg dir1\1.jpg.txt -> a.jpg.txt dir1\2.jpg -> b.jpg dir1\2.jpg.txt -> b.jpg.txt dir2\1.jpg -> c.jpg dir2\1.jpg.txt -> c.jpg.txt ... ich möchte jetzt via bash alle Dateien mit gleichem Namen (aber unterschiedlicher Extension) umbenennen -> Wie kann ich durch alle Unterverzeichnisse loopen, dabei alle Datein mit gleichen Namen aber unterschiedlicher Extension finden (wie oben in dem Beispiel immer als Paar .jpg/ .jpg.txt und die ändert sich auch nicht) und dann dieses Paar umbenennen (da wollte ich uuidgen -r nehmen)? Danke. Martin
Martin schrieb: > dabei alle Datein mit > gleichen Namen aber unterschiedlicher Extension finden (wie oben in dem > Beispiel immer als Paar .jpg/ .jpg.txt und die ändert sich auch nicht) Also ist es immer .jpg.txt -> .jpg? Oder kann es auch mal anders sein?
unter Linux gibts das Tool mmv (In Win Umgebungen via cygwin auch verfügbar) … es braucht gar kein bash Skript drumherum
Hallo. Ich habe immer ein Paar: also 1.jpg und 1.jpg.txt Davon jede Menge mit zT langen Dateinamen die auch zB einen. enthalten. Immer ein Paar will ich umbenennen in zB a.jpg und a.jpg.txt Martin
Was soll eigentlich nach "z" kommen? Ist sber eine mehr rhetorische Frage. Ich arbeite nicht für lau.
1 | #!/bin/bash
|
2 | |
3 | set -u |
4 | |
5 | # globbing ausschalten wenn dir leer
|
6 | shopt -s nullglob |
7 | |
8 | names=( "a" "b" "c" "d" ) |
9 | index=0 |
10 | |
11 | |
12 | # für debugging
|
13 | #for i in ${!names[@]}
|
14 | #do
|
15 | # echo "$i ${names[$i]}"
|
16 | #done; exit
|
17 | |
18 | for verz in * |
19 | do
|
20 | if [ -d "$verz" ] |
21 | then
|
22 | cd "$verz" |
23 | for datei in * |
24 | do
|
25 | if [ -f "$datei" ]; then |
26 | name=$(echo "$datei"|grep -oP '^(.[^\.]*)') |
27 | ext=$(echo "$datei"|grep -Po '\..*$') |
28 | echo " $datei -> ${names[$index]}${ext}" |
29 | # mv "$datei" "${names[$index]}${ext}"
|
30 | fi
|
31 | done
|
32 | cd .. |
33 | ((index++)) |
34 | fi
|
35 | done
|
36 | |
37 | shopt -u nullglob |
Musst aber aufpassen dass die namen im Array auch entspr. mind. der Anzahl der Dirs entsprechen.
Add: Das Script muss im dir liegen wo die entspr. dir1 dir2,... liegen.
Add2: Ein nullcheck auf $name und evt. $ext sollte man vorher auch noch machen falls nix im dir ist, aber wenn du dir sicher bist dass da immer Dateien liegen kann man es weglassen.
Argh! Vergiss mein Script oben, ich habe mich nur auf dein Beispiel fixiert du willst alle gleiche Namen in einem Dir finden, das ist was anderes als das was mein Script macht,das mit uuidgen habe ich auch überlesen.
Martin schrieb: > Hallo. > > Ich brauche mal eine Idee: > Gegeben sind Unterorder in denen sich Dateien befinden nach folgendem > Aufbau: > dir1\1.jpg -> a.jpg > dir1\1.jpg.txt -> a.jpg.txt > dir1\2.jpg -> b.jpg > dir1\2.jpg.txt -> b.jpg.txt > dir2\1.jpg -> c.jpg > dir2\1.jpg.txt -> c.jpg.txt > ... > > ich möchte jetzt via bash alle Dateien mit gleichem Namen (aber > unterschiedlicher Extension) umbenennen -> Hier ist dein erster Gedankenfehler: > dir1\1.jpg -> a.jpg ›1‹ ist der Dateiname, ›jpg‹ die Erweiterung > dir1\1.jpg.txt -> a.jpg.txt ›1.jpg‹ ist der Dateiname, ›txt‹ die Erweiterung
1 | #!/bin/bash
|
2 | set -u |
3 | |
4 | # globbing ausschalten wenn dir leer
|
5 | shopt -s nullglob |
6 | |
7 | names=( "a" "b" "c" "d" ) |
8 | index=0 |
9 | |
10 | for verz in * |
11 | do
|
12 | if [ -d "$verz" ] |
13 | then
|
14 | cd "$verz" |
15 | newname=$(uuidgen -r) |
16 | dateien=(*) |
17 | echo "processing dir $verz..." |
18 | for datei in "${dateien[@]}"; do |
19 | if [ -f "$datei" ]; then |
20 | name=$(echo "$datei"|grep -oP '^(.[^\.]*)') |
21 | ext=$(echo "$datei"|grep -Po '\..*$') |
22 | echo "name: $name ext:$ext" |
23 | |
24 | #weitere gleiche namen suchen
|
25 | #ineffizient aber geht
|
26 | for datei2 in "${dateien[@]}"; do |
27 | name2=$(echo "${datei2}"|grep -oP '^(.[^\.]*)') |
28 | |
29 | ext2=$(echo "${datei2}"|grep -Po '\..*$') |
30 | |
31 | if [ "$name" = "$name2" ]; then |
32 | echo " doublette found: ${datei2}" |
33 | echo " mv $datei2 ${newname}${ext2}" |
34 | fi
|
35 | done
|
36 | fi
|
37 | done
|
38 | cd .. |
39 | echo
|
40 | fi |
41 | done
|
42 | shopt -u nullglob |
Add zu Script 2: Das
1 | names=( "a" "b" "c" "d" ) |
2 | index=0 |
ist ein Überbleibsel aus der ersten Version, das kann man rauslöschen, wird nicht gebraucht.
Verbesserungen: * Die Direntries sotiert einlesen oder nach dem Einlesen sortieren. Dann beim Doublettenprüfen der inneren for-loop vom entspr. index loslaufen, dann ist die Laufzeit besser als O(n^2) wie oben. Wenn in einem dir sehr viele Dateien sind dauert das schon recht lange. * Evt kann man auch grep durch das interne String matching von bash ersetzen das ist aber nicht so mächtig und reicht evt. nicht aus, geht dann aber schneller weil nicht das externe grep aufgerufen werden muss. Also Vorlage reicht das Script oben ja erst mal.
Modeberater für Ingenieure schrieb: > Die Direntries sotiert einlesen Es ist schon Sortiert (ich glaube nach locale): https://www.gnu.org/software/bash/manual/bash.html#Filename-Expansion > After word splitting, unless the -f option has been set (see The Set > Builtin), Bash scans each word for the characters ‘*’, ‘?’, and ‘[’. > If one of these characters appears, and is not quoted, then the word > is regarded as a pattern, and replaced with an alphabetically sorted > list of filenames matching the pattern. Noch ein Tip: Statt "cd x; zeug; cd .." kann man manchmal sub shells nutzen "( cd x; zeug; )". Mit sub shells kann man allerhand state isolieren. Variablen, das cwd, Dateiumleitungen, usw.
untested:
1 | #!/bin/sh
|
2 | txt="txt" |
3 | mvpairs() { |
4 | for fn; do |
5 | ext="${fn##*.} |
6 | test -n "$ext" -a -f "$fn" -a -f "$fn.$txt" && { |
7 | set -- $(md5sum "$fn") |
8 | dfn="$(dirname "$fn")/$1.$ext" |
9 | if test -f "$dfn"; then |
10 | echo "dup: '$fn' already exists as '$dfn'" |
11 | else
|
12 | echo "moving '$fn[.$txt]' -> '$dfn[.$txt]'" |
13 | mv "$fn" "$dfn" |
14 | mv "$fn.$txt" "$dfn.$txt" |
15 | fi
|
16 | }
|
17 | done
|
18 | }
|
19 | #exec mvpairs "$@" |
20 | mvpairs */*.jpg
|
> untested
Mist... mindestens ein " fehlt :-/
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.