Loop melalui file tidak termasuk direktori

11

Saya perlu skrip saya untuk melakukan sesuatu pada setiap file di direktori saat ini tidak termasuk sub-direktori.

Misalnya, di jalur saat ini, ada 5 file, tetapi 1 di antaranya adalah folder (sub-direktori). Skrip saya harus mengaktifkan perintah yang diberikan sebagai argumen saat menjalankan skrip tersebut. Yaitu "bash script wc -w" harus memberikan jumlah kata setiap file dalam direktori saat ini, tetapi tidak ada folder, sehingga output tidak pernah memiliki baris "/ sub / dir: Is a directory".

Skrip saya saat ini:

#!/bin/bash
dir=`pwd`
for file in $dir/*
do
    $* $file
done

Saya hanya perlu mengecualikan direktori untuk loop, tapi saya tidak tahu caranya.

Tõnis Piip
sumber

Jawaban:

11
#!/bin/bash -

for file in "$dir"/*
do
  if [ ! -d "$file" ]; then
      "$@" "$file"
  fi
done

Perhatikan bahwa itu juga mengecualikan file yang bertipe symlink dan di mana symlink memutuskan untuk file direktori jenis (yang mungkin apa yang Anda inginkan).

Alternatif (dari komentar), periksa hanya file:

for file in "$dir"/*
do
  if [ -f "$file" ]; then
      "$@" "$file"
  fi
done
laktak
sumber
@roaima ide bagus!
laktak
2
Lebih baik digunakan if [ -f "$file" ]; then .... Bukan direktori yang akan mengembalikan tidak hanya file biasa tetapi juga soket dan symlink.
JRFerguson
@ JRFerguson berdasarkan pertanyaan OP, saya akan mengatakan bahwa memasukkan soket dan pipa akan menjadi ide yang sangat buruk. Adapun symlink, mereka sudah termasuk secara implisit ! -d.
roaima
Saya menggunakan [-f $ file] dalam skrip terakhir saya. Perhatikan kurangnya tanda kutip dalam kondisi if. Hampir di mana-mana saya melihat ada tanda kutip sekitar $ file, namun saya harus menghapusnya agar skrip saya berfungsi.
Tõnis Piip
3

Inilah alternatif untuk menggunakan loop for jika apa yang perlu Anda lakukan adalah sederhana (dan tidak melibatkan variabel pengaturan di shell & c utama).

Anda dapat menggunakan finddengan -execdan menggunakan -maxdepth 1untuk menghindari recursing ke subdirektori.

[ -n "$1" ] && find "$dir" -type f -mindepth 1 -maxdepth 1 -exec "$@" "{}" \;

Itu [ -n "$1" ]ada untuk menghindari mengeksekusi semua file dalam direktori ketika skrip tidak memberikan argumen.

Gregory Nisbet
sumber
2

Di zsh, Anda dapat menggunakan kualifikasi glob untuk membatasi kecocokan wildcard berdasarkan jenis file. Misalnya, menambahkan (.)setelah pola membatasi ke file biasa.

wc -w *(.)

Untuk mengatasi nama file yang dimulai dengan -atau ., gunakan wc -c -- *(.N)atau wc -c ./*(.N). Jika Anda ingin menyertakan tautan simbolik ke file biasa juga, buatlah itu *(-.).

Kerang umum lainnya tidak memiliki fitur seperti itu, jadi Anda perlu menggunakan beberapa mekanisme berbeda untuk memfilter menurut file seperti menguji tipe file dalam satu lingkaran atau find.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

Bash untuk loop tidak termasuk sub-direktori ('/') dan tautan (@):

for f in `ls|egrep -v '/|@'`; do echo $f; done
James Armstrong
sumber