Перебирать файлы, исключая каталоги

11

Мне нужен мой скрипт, чтобы что-то делать с каждым файлом в текущем каталоге, исключая любые подкаталоги.

Например, в текущем пути есть 5 файлов, но 1 из них является папкой (подкаталогом). Мой скрипт должен активировать команду, указанную в качестве аргумента при запуске указанного скрипта. Т.е. "bash script wc -w" должен давать количество слов для каждого файла в текущем каталоге, но не для каких-либо папок, чтобы в выводе никогда не было строк "/ sub / dir: Is a directory".

Мой текущий скрипт:

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

Мне просто нужно исключить каталоги для цикла, но я не знаю как.

Тынис Пийп
источник

Ответы:

11
#!/bin/bash -

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

Обратите внимание, что он также исключает файлы, которые имеют тип symlink и где символическая ссылка преобразуется в файл типа directory (что, вероятно, то, что вам нужно).

Альтернатива (из комментариев), проверка только на наличие файлов:

for file in "$dir"/*
do
  if [ -f "$file" ]; then
      "$@" "$file"
  fi
done
laktak
источник
@roaima хорошая идея!
Лактак
2
Лучше использовать if [ -f "$file" ]; then .... Не каталог будет возвращать не только обычные файлы, но и сокеты и символические ссылки.
JRFerguson
@JRFerguson, основываясь на вопросе ОП, я бы сказал, что включение сокетов и труб было бы действительно плохой идеей. Что касается символических ссылок, они неявно включены с ! -dуже.
Roaima
Я использовал [-f $ file] в своем последнем скрипте. Обратите внимание на отсутствие кавычек в условии if. Почти везде я смотрел кавычки вокруг $ file, но мне пришлось удалить их, чтобы мой скрипт работал.
Тынис Пийп
3

Вот альтернатива использованию цикла for, если то, что вам нужно сделать, просто (и не требует установки переменных в основной оболочке & c).

Вы можете использовать findс -execи использовать, -maxdepth 1чтобы избежать повторения в подкаталоге.

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

Он [ -n "$1" ]существует для того, чтобы избежать выполнения всех файлов в каталоге, когда сценарию не переданы никакие аргументы.

Грегори Нисбет
источник
2

В zsh вы можете использовать глобальные квалификаторы для ограничения совпадений по шаблону по типу файла. Например, добавление (.)после шаблона ограничивает его обычными файлами.

wc -w *(.)

Чтобы справиться с именами файлов, начинающимися с -или ., используйте wc -c -- *(.N)или wc -c ./*(.N). Если вы хотите включить символические ссылки и в обычные файлы, сделайте это *(-.).

Другие распространенные оболочки не имеют такой функции, поэтому вам нужно использовать какой-то другой механизм для фильтрации по файлам, такой как тестирование типов файлов в цикле или find.

Жиль "ТАК - перестань быть злым"
источник
0

Bash for loop, исключая подкаталоги ('/') и ссылки (@):

for f in `ls|egrep -v '/|@'`; do echo $f; done
Джеймс Армстронг
источник