Ordnerstruktur reduzieren

8

Ich habe diese Ordnerstruktur:

├── foo1
   ├── bar1.txt
   └── bar2.txt
├── foo2
   ├── bar3.txt
   └── bar4 with a space.txt
└── foo3
    └── qux1
        ├── bar5.txt
        └── bar6.txt

dass ich darauf eingehen möchte, mit einem Unterstrich zwischen den einzelnen Ordnerebenen:

├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt

Ich habe mich umgesehen und keine Lösung gefunden, die funktioniert. Meistens denke ich, weil mein Problem zwei Besonderheiten aufweist: Es gibt möglicherweise mehr als eine Ordnerebene im Stammverzeichnis und auch, weil einige Dateien möglicherweise Leerzeichen enthalten.

Irgendeine Idee, wie man dies in Bash erreicht? Vielen Dank!

Edit : Running Gleen Jackman vorgeschlagene Antwort Ich bekomme diese:

Geben Sie hier die Bildbeschreibung ein

Es gibt zwei Unterstriche für den Ordner der ersten Ebene. Irgendeine Idee, wie man dies entweder vermeidet oder einfach umbenennt, so dass dies nur ein Unterstrich ist? Vielen Dank.

Nunos
quelle

Antworten:

15
find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;

Entfernen echoSie , wenn Sie zufrieden sind, dass es funktioniert. Machen Sie sich keine Sorgen, dass die Echo-Befehle keine Anführungszeichen anzeigen. Das Skript behandelt Dateien mit Leerzeichen ordnungsgemäß.

Wenn Sie die jetzt leeren Unterverzeichnisse entfernen möchten:

find */ -depth -type d -exec echo rmdir '{}' \; 
Glenn Jackman
quelle
Hallo. Das ist großartig! Vielen Dank. Das hat den Trick fast vollständig gemacht. Ich habe nur ein kleines Problem, nämlich foo1__qux1_bar5.txtzwei Unterstriche in der ersten Ordnerebene. Ich habe versucht, mit deiner Bash-Linie herumzuspielen, aber nichts schien zu funktionieren. Vielleicht muss ich etwas hinzufügen?
Nunos
@unos, ich kann dieses Verhalten nicht reproduzieren
Glenn Jackman
"Ja wirklich?" Seltsam. Ich habe gerade meine Antwort mit einigen weiteren Informationen aktualisiert. Können Sie bitte einen Blick darauf werfen? Vielen Dank.
Nunos
1
huh. OK, wechseln Sie "${file//\//_}"zu "${file//+(/)/_, und wenn dies ein Skript ist,shopt -s extglob
Glenn Jackman
Ich hatte auch das Problem mit den beiden Unterstrichen. Leider hat das Ändern des von Ihnen vorgeschlagenen Befehls bei mir nicht funktioniert. Ich habe diese Antwort jedoch auf AskDifferent gefunden: apple.stackexchange.com/a/254224/122152 Laut der Antwort verwendet macOS möglicherweise BSD find. Eine Problemumgehung kann darin bestehen, Findutils zu verwenden. Es kann mit Homebrew mit brew install findutilsund dann mit gfindanstelle von installiert werden find. Das hat bei mir funktioniert.
Intagli
5

Verwenden der Umbenennung von Perl:

find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;

AUSGABE

$ find -type f
./foo2_bar4 whit a space.txt
./foo3_qux1_bar6.txt
./foo2_bar3.txt
./foo3_qux1_bar5.txt
./foo1_bar2.txt
./foo1_bar1.txt

HINWEIS

  • Ich benutze einen negativen Blick nach hinten (?<!\.) , um den ersten nicht zu berühren./
  • Ich behalte die leeren Verzeichnisse, fühle mich frei zu:

    find . -depth -type d -exec rm {} \;

Warnung Es gibt andere Tools mit demselben Namen, die dies möglicherweise können oder nicht. Seien Sie also vorsichtig.

Wenn Sie den folgenden Befehl ausführen ( GNU)

$ file "$(readlink -f "$(type -p rename)")"

und du hast ein Ergebnis wie

.../rename: Perl script, ASCII text executable

und enthält nicht:

ELF

dann scheint dies das richtige Werkzeug zu sein =)

Wenn nicht, um es zum Standard (normalerweise bereits der Fall) zu machen Debianund abzuleiten wie Ubuntu:

$ sudo update-alternatives --set rename /path/to/rename

(Ersetzen Sie /path/to/renameden Pfad Ihres perl's renameBefehls.


Wenn Sie diesen Befehl nicht haben, durchsuchen Sie Ihren Paketmanager, um ihn zu installieren, oder führen Sie ihn manuell aus


Last but not least wurde dieses Tool ursprünglich von Larry Wall, dem Vater des Perl, geschrieben.

Gilles Quenot
quelle
... -type d -exec rmdir ...?
JJoao
Ich habe anscheinend keine Umbenennung zur Verfügung. Wie genau kann ich sie erhalten und ist diese normalerweise in einem UNIX-System verfügbar? Vielen Dank.
Nunos
@nunos Es ist ein Perl-Skript. Es ist unter dem Namen perl-renamein Arch Linux und prenamein Debian-basierten Systemen verfügbar.
Muru
renameErklärungen hinzugefügt
Gilles Quenot
1

mit pax...

pax -Xrwls '|/|_|g' */ "$PWD"

Dadurch wird im aktuellen Verzeichnis ein Hardlink zu allen Dateien in den untergeordneten Verzeichnissen erstellt, durch die ein _Ersatz ersetzt wird /. Sie können dann die Ergebnisse überprüfen und alle untergeordneten Verzeichnisse mit ...

rm -rf */

... sobald Sie überprüft haben, dass die Ergebnisse Ihren Wünschen entsprechen.

mikeserv
quelle
0

Sie können es mit dem folgenden Befehl versuchen.

$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;

Der obige Befehl verschiebt die Dateien und das Verzeichnis bleibt erhalten, das später entfernt werden kann.

$ ls
foo1_bar1.txt  foo1_bar2.txt  foo2_bar3.txt  foo2_bar4.txt  foo3_bar5.txt  foo3_bar6.txt
Kannan Mohan
quelle