Meratakan struktur folder

8

Saya memiliki struktur folder ini:

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

bahwa saya ingin meratakan ini, dengan garis bawah di antara setiap tingkat folder:

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

Saya telah melihat-lihat dan saya belum menemukan solusi yang berfungsi, kebanyakan saya pikir karena masalah saya memiliki dua kekhasan: mungkin ada lebih dari satu level folder di dalam root dan juga karena beberapa file mungkin memiliki ruang.

Adakah yang tahu bagaimana melakukannya di bash? Terima kasih!

Sunting : Menjalankan gleen jackman jawaban yang diajukan saya dapatkan ini:

masukkan deskripsi gambar di sini

Ada dua garis bawah untuk folder tingkat pertama. Adakah yang tahu bagaimana cara menghindari ini atau hanya mengganti namanya jadi itu hanya satu garis bawah? Terima kasih.

nunos
sumber

Jawaban:

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

hapus echojika Anda puas itu berfungsi. Jangan khawatir bahwa perintah yang di-echo tidak menunjukkan tanda kutip, skrip akan menangani file dengan spasi dengan benar.

Jika Anda ingin menghapus subdirektori yang sekarang kosong:

find */ -depth -type d -exec echo rmdir '{}' \; 
glenn jackman
sumber
Hei. Itu luar biasa! Terima kasih. Itu berhasil hampir seluruhnya. Saya hanya mengalami masalah kecil, yang saya dapatkan foo1__qux1_bar5.txt, dua garis bawah di tingkat folder pertama itu. Sudah mencoba main-main dengan bash line Anda tapi sepertinya tidak ada yang berhasil. Mungkin saya perlu menambahkan sesuatu?
nunos
@nunos, saya tidak bisa mereproduksi perilaku itu
glenn jackman
Betulkah? Aneh. Saya baru saja memperbarui jawaban saya dengan beberapa info lagi. Bisakah Anda melihatnya? Terima kasih.
nunos
1
Hah. OK, ubah "${file//\//_}"menjadi "${file//+(/)/_, dan jika ini adalah naskah,shopt -s extglob
glenn jackman
Saya punya masalah dengan dua garis bawah juga. Sayangnya, mengubah perintah seperti yang Anda sarankan tidak berhasil untuk saya. Saya menemukan jawaban ini di AskDifferent: apple.stackexchange.com/a/254224/122152 Menurut jawabannya, macOS mungkin menggunakan BSD find. Solusinya adalah menggunakan findutils. Itu dapat diinstal menggunakan homebrew dengan brew install findutilsdan kemudian menggunakan gfindalih-alih find. Ini berhasil untuk saya.
intagli
5

Menggunakan nama perl:

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

KELUARAN

$ 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

CATATAN

  • Saya menggunakan tampilan negatif di belakang (?<!\.) untuk tidak menyentuh yang pertama./
  • Saya menyimpan dir kosong, jangan ragu untuk:

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

peringatan Ada alat lain dengan nama yang sama yang mungkin atau mungkin tidak dapat melakukan ini, jadi berhati-hatilah.

Jika Anda menjalankan perintah berikut ( GNU)

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

dan Anda memiliki hasil seperti

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

dan tidak mengandung:

ELF

maka ini tampaknya menjadi alat yang tepat =)

Jika tidak, untuk menjadikannya default (biasanya sudah terjadi) Debiandan turunannya seperti Ubuntu:

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

(ganti /path/to/renameke jalur perl's renameperintah Anda .


Jika Anda tidak memiliki perintah ini, cari manajer paket Anda untuk menginstalnya atau melakukannya secara manual


Terakhir, alat ini awalnya ditulis oleh Larry Wall, ayah Perl.

Gilles Quenot
sumber
... -type d -exec rmdir ...
JJoao
Saya sepertinya tidak memiliki nama yang tersedia .. Bagaimana saya bisa mendapatkannya dan apakah ini biasanya tersedia dalam sistem UNIX? Terima kasih.
nunos
@nunos Ini skrip Perl. Ini tersedia dengan nama perl-renamedi Arch Linux, dan prenamedalam sistem berbasis Debian.
muru
Ditambahkan renamepenjelasan
Gilles Quenot
1

dengan pax...

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

Itu akan membuat hardlink di direktori saat ini ke semua file di direktori turunannya dengan _untuk /. Anda kemudian dapat memeriksa hasilnya dan menghapus semua direktori anak dengan ...

rm -rf */

... setelah Anda memverifikasi hasilnya sesuai dengan keinginan Anda.

mikeserv
sumber
0

Anda dapat mencoba dengan perintah di bawah ini.

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

Perintah di atas akan memindahkan file dan direktori akan tetap yang bisa dihapus nanti.

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