Избегайте совпадений.и .. при циклическом просмотре файлов в оболочке POSIX - PullRequest
1 голос
/ 08 июля 2019

Я хочу сделать что-то для каждого файла в каталоге, поэтому у меня есть

for f in /path/* /path/.*; do
  [ -e "$f" ] || continue
  do_thing "$f"
done

К сожалению, это также соответствует . и .., что в данном случае нежелательно. Как мне избежать совпадения . и ..?

Ответы [ 4 ]

3 голосов
/ 08 июля 2019

Чтобы запустить do_thing для каждого файла в текущем каталоге, попробуйте:

find /path -maxdepth 1 -type f -exec do_thing {} \;

Этот метод позволяет избежать зацикливания и избежать анализа ls.

Как это работает

  • find /path

    Запускает команду find и указывает найти для поиска в каталоге /path.

  • -maxdepth 1

    Это говорит find искать только в текущем каталоге и не переходить в подкаталоги.

  • -type f

    Это говорит find, что мы ищем только обычные файлы (не каталоги).

  • -exec do_thing {} \;

    Эта команда запускает команду do_thing для каждого найденного файла.

1 голос
/ 08 июля 2019

следующее должно соответствовать всем скрытым файлам и исключать . и ..

for f in `ls -a /path | grep -vE "^\.{1,2}$"`; do
    # whatever
done

-v инвертирует совпадение, \. соответствует буквальной точке, {1,2} соответствует емуодин или два раза ^ и $ соответствуют началу и концу строки соответственно.флаг -E обеспечивает работу синтаксиса {m,n}.Задние штыри `предотвращают удушение оболочки на трубе.(Хихи)

1 голос
/ 08 июля 2019
clean_path=`ls -a ~/example_dir/ | grep -v -P "^\.{1,2}$"`
for f in $clean_path; do
    do_thing $f;
done

ls -a ~/some_dir команда для распечатки всего файла в каталоге some_dir.

^\.{1,2}$ означает, соответствует строка, начинающаяся (^) с точки (* 1008)*) точка может содержать от 1 до 2 символов ({1,2}), и это конец строки ($), поэтому она будет соответствовать . и ...

Использование backtick в команде означает «обработать результат этой команды».

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

Вуаля, теперь вы можете повторять их, так как результат разделяется только пробелом.

1 голос
/ 08 июля 2019

Как насчет использования if, чтобы избежать их?

tmp_path=/path
for f in $tmp_path/* $tmp_path/.*; do
  if [ "$f" == "$tmp_path/." ] || [ "$f" == "$tmp_path/.." ]
  then
    continue
  fi
  [ -e "$f" ] || continue
  echo "$f"
done
...