Umbenennen von Ordnern mithilfe einer TXT-Datei

7

Ich arbeite in meinem Terminal mit Bash und versuche, die Ordner umzubenennen:

1
2
3
4
5

Ich möchte sie gemäß a.txt-Datei umbenennen:

a 2
c 3
d 5
e 1
b 4

Die Reihenfolge in der TXT-Datei ist völlig zufällig. Ich hoffe, einen Weg zu finden, wie ich den Ordner umbenennen kann, damit sie werden:

1 > e
2 > a
3 > c
4 > b
5 > d

Gibt es eine Möglichkeit, dies zu tun?

Vielen Dank!

Ditte
quelle
1
Die Frage geht davon aus, dass nicht mehr als 26 Fles umbenannt werden müssen. Ist das korrekt?
Jacob Vlijm
Ich habe 1 Datei und 200 Ordner zum Umbenennen :(
Ditte
Ah, das macht die Frage interessanter. Gibt es eine Chance auf Namenskonflikte?
Jacob Vlijm
1
@ BharadwajRaju Ich habe bereits dafür gestimmt.
Muru
1
@Ditte Sie verwenden OS X und iOS. Warum hier fragen, wo es nicht zum Thema gehört? Fragen Sie bei SuperUser oder AskDifferent.
UniversallyUniqueID

Antworten:

4

Angenommen, die Namen in der Liste enthalten keine Leerzeichen außer zwischen den Namen, benennt das folgende Skript Ordner aus einer Textdatei rekursiv um . Es liest die Zeilen der Datei, teilt sie in zwei (neuer Name, alter Name) auf und benennt vorkommende Ordner, die durch die zweite Zeichenfolge in der Zeile benannt sind, in die erste Zeichenfolge in der Zeile um.

Dies geschieht , wie rekursiv erwähnt , von unten nach oben im Verzeichnisbaum. Dies verhindert Probleme im Skript und versucht, Ordner in möglicherweise bereits umbenannten übergeordneten Ordnern umzubenennen.

#!/usr/bin/env python
import os
import shutil

# -- set the (absolute) path to the targeted folder below
dr = "/home/jacob/Bureaublad/testfolder"
# -- set the path to the textfiles below
ren = "/home/jacob/Bureaublad/testfolder/renfile.txt"

renlist = [cpl for cpl in [l.split() for l in open(ren).readlines()] if cpl]
currnames = [r[1] for r in renlist]

for root, dirs, files in os.walk(dr, topdown = False):
    for dr in dirs:
        try:
            # look up the name, pass if not in the list
            i = currnames.index(dr)
        except ValueError:
            pass
        else:
            newname = renlist[i][0]
            shutil.move(root+"/"+dr, root+"/"+newname)

Wie benutzt man

  1. Kopieren Sie das Skript in eine leere Datei (in einem Nur-Text- Editor) und speichern Sie es unterrename.py
  2. Legen Sie im Kopfabschnitt des Skripts die tatsächlichen Pfade zur Textdatei und zum Verzeichnis fest
  3. Führen Sie es mit dem Befehl (in einem Terminal) aus:

    python /path/to/rename.py

Erläuterung

Das Skript:

  • erstellt eine Liste der Namen- Paare : newname / oldname
  • Mit Python durchsucht os.walk()es Ihre Verzeichnisse rekursiv von unten nach oben.
  • Wenn der Ordnername mit dem zweiten Element eines Namenspaars übereinstimmt, wird der Ordner in den Vornamen umbenannt.
  • Wenn der Name des Ordners nicht aufgeführt ist, bleibt er unberührt.
Jacob Vlijm
quelle
Ist das Skript vollständig?
Ajay Kulkarni
Ja, aber
ich
@jacobvlijm Danke! Ändere ich einfach die Pfade zu meinen Ordnern und meinem Text und kopiere sie dann in mein Terminal. Habe noch nie Python benutzt
Ditte
@Ditte nono, siehe Beschreibung ...
Jacob Vlijm
1
@Ditte In welcher Anwendung haben Sie es eingefügt? Es sollte sich um eine Klartextanwendung handeln. siehe stackoverflow.com/a/21639459/1391444
Jacob Vlijm
6

Sie könnten verwenden xargsmit mv:

xargs -r -a /path/to/file.txt -L1 mv

(Vorausgesetzt, Sie befinden sich in dem Verzeichnis, in dem sich die Dateien befinden).

xargs konvertiert Eingaben in Argumente für einen Befehl.

  • -a fooEingabe von lesen foo.
  • -L1 um genau eine Eingabezeile pro Befehlsaufruf zu verwenden.
  • -r um zu vermeiden, dass der Befehl ausgeführt wird, wenn die Zeile leer ist

Verwenden Sie beispielsweise echo mvanstelle von mv, um die ausgeführten Befehle anzuzeigen:

$ xargs -r -a foo.txt -L1 echo mv
mv a 2
mv c 3
mv d 5
mv e 1
mv b 4

Sie können auch die -pOption verwenden, um xargsvor dem Ausführen des Befehls eine Bestätigung vorzunehmen :

$ xargs -r -p -a foo.txt -L1 mv
mv a 2 ?...n
mv c 3 ?...n
mv d 5 ?...y
mv e 1 ?...mv: cannot stat d’: No such file or directory
n
mv b 4 ?...
muru
quelle
funktioniert per Definition nicht rekursiv in einem Verzeichnis, muss von unten nach oben sein.
Jacob Vlijm
Es heißt: xargs: illegale Option - r Verwendung: xargs [-0opt] [-E eofstr] [-I replstr [-R Ersetzungen]] [-J replstr] [-L Nummer] [-n Nummer [-x] ] [-P maxprocs] [-s Größe] [Dienstprogramm [Argument ...]]
Ditte
@Ditte Es ist eine legale Option ab mindestens 12.04: manpages.ubuntu.com/manpages/precise/en/man1/xargs.1.html Welche Ubuntu-Version verwenden Sie?
Muru
Ich bin auf iOS. Ist das ein Problem? Ich habe ziemlich viele Antworten von hier verwendet, als ich Informationen aus großen Datensätzen extrahiert habe und es normalerweise gut funktioniert. Hoffe, dass ich Sie nicht unnötig
Ditte
2
Ja, das ist ein Problem. Fragen zu Nicht-Ubuntu-Systemen sollten unter Unix und Linux gestellt werden . Wie hier zu sehen ist, können Befehle unterschiedlich sein.
Muru
2

Es gibt einen Eintrag pro Zeile in der a.txtDatei, daher enthalten die aufgelisteten Namen kein Zeichen \n(neue Zeile), oder?

Eine Zeile enthält 2 Namen, die durch ein Leerzeichen getrennt sind. Die Namen enthalten also kein Leerzeichen , oder? (oder eine andere Möglichkeit wäre, eine feste Länge für die aufgelisteten Namen zu verwenden).

Probieren Sie es aus, wenn die Namen weder Zeichen \nnoch spaceZeichen enthalten:

awk '{printf("%s\0%s\0",$2,$1)}' a.txt | xargs -0 -L 2 mv

awkwird verwendet, um die Reihenfolge der Namen in aus der a.txtDatei gelesenen Zeilen umzukehren . \0wird verwendet, um die Namen zu trennen, wenn sie in der Standardausgabe gedruckt werden.

xargs liest die Standardeingabe:

  • -0: \0wird als Trennzeichen für die aus der Standardeingabe gelesenen Elemente verwendet
  • -L 2 mvDer mvBefehl : wird mit jeweils 2 Parametern aufgerufen.

Die Prüfung:

$ ls -al
total 40
drwxrwxr-x  7 stacko stacko  4096 May 31 11:25 .
drwxrwxr-x 21 stacko stacko 12288 May 31 11:23 ..
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 1
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 2
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 3
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 4
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 5
-rw-rw-r--  1 stacko stacko    20 May 31 11:24 a.txt
$ cat a.txt
a 2
c 3
d 5
e 1
b 4
$ awk '{printf("%s\0%s\0",$2,$1)}' a.txt | xargs -0 -L 2 mv -v
'2' -> 'a'
'3' -> 'c'
'5' -> 'd'
'1' -> 'e'
'4' -> 'b'
$ ls -al
total 40
drwxrwxr-x  7 stacko stacko  4096 May 31 11:26 .
drwxrwxr-x 21 stacko stacko 12288 May 31 11:23 ..
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 a
-rw-rw-r--  1 stacko stacko    20 May 31 11:24 a.txt
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 b
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 c
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 d
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 e
Jay Jargot
quelle
2

In dem oben gezeigten einfachen Fall, in dem jede Zeile zwei "Wörter" enthält, das Zielverzeichnis und den neuen Namen, und in dem keine Leerzeichen enthalten können, können Sie einfach Folgendes tun:

while read -r from to; do mv "$from" "$to"; done < file 

Dadurch wird jede Zeile gelesen, in der filedie erste Zeichenfolge (bis zum ersten Leerzeichen) $fromund der Rest der Zeile zugewiesen $tound dann mvauf jeder Zeile ausgeführt wird .

Terdon
quelle