Lintasi semua subdirektori dan lakukan sesuatu di skrip Unix shell

17

Saya ingin skrip shell saya mengunjungi semua subdirektori dalam direktori utama. Lakukan sesuatu di direktori, mengirim output ke file spool dan pindah ke direktori berikutnya. Pertimbangkan Main Dir = / tmp Sub Dir = ABCD (Empat sub direktori)

Ashish
sumber
2
OKE, tolong tunjukkan skrip Anda sejauh ini. Bagian mana yang memberimu masalah?
terdon

Jawaban:

22

Gunakan satu forlingkaran:

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

Itu hanya mencari subdirektori dari direktori /path/to/dir. Perhatikan bahwa contoh sederhana di atas akan gagal jika nama direktori berisi spasi putih atau karakter khusus. Pendekatan yang lebih aman adalah:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

Atau di dataran bash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(perhatikan bahwa bertentangan dengan finditu orang juga menganggap symlink ke direktori dan mengecualikan yang tersembunyi)

kekacauan
sumber
1
setidaknya tunjukkan batasan dan risiko yang terkait dengan pemrosesan output findseperti itu.
Stéphane Chazelas
Hai ... saya mencoba menjalankan di bawah ini untuk loop untuk d dalam $ (temukan / cadangan / ASHISH -maxdepth 1 -type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d
Ashish
Hai ... Saya mencoba loop di bawah ini. untuk d dalam $ (temukan / cadangan / ASHISH -maxdepth 1 -type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d Hasil yang diharapkan adalah ls -ltr dari semua subdirektori . Di atas lingkaran tidak berfungsi
Ashish
1

Saya seorang bashpemula yang lengkap , tetapi seorang veteran PBB * X. Meskipun tidak diragukan lagi ini dapat dilakukan dalam skrip Bash shell, di masa lalu kami terbiasa find [-maxdepth <levels>] <start-dir> -exec <command> ;untuk mencapai ini. Anda dapat melakukan man finddan bermain-main, mungkin sampai seseorang memberitahu Anda bagaimana melakukannya bash!

JonBrave
sumber
Saya sangat tersanjung bahwa jawaban "garis besar" saya di sini telah menerima suara. Namun, mengapa jawaban @chaos di bawah ini menerima suara turun? (Sebagai pendatang baru di forum ini, saya tidak dapat memposting komentar ini terhadap jawabannya, hanya terhadap saya sendiri.) Saran kedua adalah benar untuk solusi skrip shell, dan menghindari overhead menjalankan findperintah eksternal .
JonBrave
Yang kedua memang benar. Yang pertama akan gagal jika nama direktori berisi spasi putih atau karakter khusus (garis miring terbalik misalnya). Lihat hasil edit yang saya buat untuk jawabannya untuk versi yang aman.
terdon
Saya setuju. Itu adalah jawaban kedua, satu-satunya shell yang saya puji.
JonBrave
Saya tahu, saya baru saja menjelaskan downvote (yang saya tidak berikan).
terdon
Saya memang melemparkannya. The $(find...)hal yang praktek yang buruk .
Stéphane Chazelas
1

Sepertinya Anda menginginkan nama file di bawah masing-masing subdir; yang ls -l | awktidak cukup kuat, untuk apa jika mereka nama file terdiri spasi dan / atau baris baru? Di bawah ini findakan berfungsi bahkan untuk mereka findyang tidak memiliki kesempatan -maxdepthuntuk mereka:

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

sumber
0

Saya mendapat solusinya. Perintah find di bawah ini memenuhi persyaratan saya.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;
Ashish
sumber
0

Mungkin juga menggunakan ls, grep, dan tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

du / sed juga dapat digunakan sebagai pemilih jika ls Anda tidak memiliki opsi di atas

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

Mungkin penting untuk mencatat contoh-contoh ini mengembalikan direktori tersembunyi dan mengecualikan direktori induk dan saat ini

JGurtz
sumber
1
(1)  lstulis satu file per baris (apa yang -1ditentukan opsi) secara default ketika output standar adalah pipa (jadi itu berlebihan dalam jawaban Anda). (2) Mengurai output lsadalah ide yang buruk - lihat ini dan ini . Jawaban pertama Anda akan gagal jika direktori memiliki spasi (atau baris baru) dalam nama mereka, dan semua akan gagal jika mereka memiliki baris baru dalam nama mereka. (3) Anda harus selalu mengutip variabel shell (misalnya, "$dir") kecuali Anda memiliki alasan kuat untuk tidak melakukannya, dan Anda yakin tahu apa yang Anda lakukan.
Scott
Poin bagus, Scott. Meninggalkan jawabannya sebagai, untuk banyak sistem tanpa direktori yang dinamai mengerikan, saya pikir itu mungkin masih berguna untuk yang pertama.
JGurtz