![Ordnerstruktur abflachen](https://rvso.com/image/36020/Ordnerstruktur%20abflachen.png)
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:
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 {} \;
Es 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) Debian
und verwenden Sie eine Ableitung wie Ubuntu
:
$ sudo update-alternatives --set rename /path/to/rename
(Ersetzen Sie es /path/to/rename
durch den Pfad Ihres perl's rename
Befehls.
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