Ordnerstruktur abflachen

Ordnerstruktur abflachen

Ich habe diese Ordnerstruktur:

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

die ich folgendermaßen zusammenfassen 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, aber keine funktionierende Lösung gefunden. Das liegt hauptsächlich daran, dass mein Problem vermutlich zwei Besonderheiten aufweist: Es könnte mehr als eine Ordnerebene innerhalb der Stammordnerebene geben und außerdem könnten einige Dateien Leerzeichen enthalten.

Irgendeine Idee, wie man das in Bash erreichen kann? Danke!

Bearbeiten: Beim Ausführen der von Gleen Jackman vorgeschlagenen Antwort erhalte ich Folgendes:

Bildbeschreibung hier eingeben

Für den Ordner der ersten Ebene gibt es zwei Unterstriche. Irgendeine Idee, wie man das entweder vermeiden oder ihn einfach umbenennen kann, sodass nur ein Unterstrich übrig bleibt? Danke.

Antwort1

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

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

Wenn Sie die jetzt leeren Unterverzeichnisse entfernen möchten:

find */ -depth -type d -exec echo rmdir '{}' \; 

Antwort2

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

NOTIZ

  • Ich benutze einnegativer Blick hinter (?<!\.)nicht den ersten berühren./
  • Ich behalte die leeren Verzeichnisse, Sie können gerne:

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

WarnungEs gibt andere Tools mit demselben Namen, die dazu möglicherweise in der Lage sind, möglicherweise aber auch nicht. Seien Sie also vorsichtig.

Wenn Sie den folgenden Befehl ausführen ( GNU)

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

und Sie haben ein Ergebnis wie

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

und nicht enthalten:

ELF

dann scheint dies das richtige Werkzeug zu sein =)

Wenn nicht, machen Sie es zum Standard (normalerweise bereits der Fall) Debianund verwenden Sie eine Ableitung wie Ubuntu:

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

(Ersetzen Sie es /path/to/renamedurch den Pfad Ihres perl's renameBefehls.


Wenn Sie diesen Befehl nicht haben, suchen Sie in Ihrem Paketmanager nach ihm odermach es manuell


Und nicht zuletzt wurde dieses Tool ursprünglich von Larry Wall, dem Vater von Perl, geschrieben.

Antwort3

mitpax...

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

Dadurch wird im aktuellen Verzeichnis ein Hardlink zu allen Dateien in seinen Unterverzeichnissen erstellt, wobei ein _ersetzt wird /. Sie können dann die Ergebnisse prüfen und alle Unterverzeichnisse mit entfernen...

rm -rf */

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

Antwort4

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 und kann später entfernt werden.

$ ls
foo1_bar1.txt  foo1_bar2.txt  foo2_bar3.txt  foo2_bar4.txt  foo3_bar5.txt  foo3_bar6.txt

verwandte Informationen