Цикл ksh: «for dir in find .. do» не работает, в отличие от «for dir in ls .. do»

Я пробовал историю -c, но история возвращается, как только мы выходим и снова открываемся. Это мне помогло.

cat /dev/null > ~/.bash_history && history -c && exit

Это очищает историю, сохраненную в файле истории, а также историю в текущем сеансе (чтобы она не сохранялась в файл при выходе bash). Затем он выходит из оболочки. Следующий сеанс оболочки не будет иметь истории.

0
10.08.2017, 01:27
4 ответа

Изменить на это:

for dir in $(find. -maxdepth 1 -type d | grep -v \\.$ | awk -F'./' '{print $2}')
do 
  echo "dir: $dir"
done

Я не могу объяснить, почему это работает, но я знаю, что вы почти всегда должны использовать $()вместо обратных кавычек.

1
28.01.2020, 02:15

Вы слишком усердно пытаетесь получить каталоги в текущем каталоге. Все, что вам нужно сделать, это:

for dir in */; do echo "dir: $dir"; done
#.........^^

Если вы хотите хранить их в массиве:

dirs=( */ )
4
28.01.2020, 02:15

Проблема с выражением grep-. Он будет соответствовать всем именам каталогов, оканчивающимся на ., но также кажется, что он каким-то образом искажает вывод, чтобы запутать for. Есть много вещей, которые вы можете сделать по этому поводу.

  • Изменение выражения grep на grep -v "^\.$", вероятно, будет более правильным (, так как оно будет соответствовать только каталогу .)и будет работать в вашем циклеfor-

  • Как уже указывал @Jesse _b, по многим причинам лучше использовать выражение $(..)для выполнения. Это решит вашу непосредственную проблему, но не устранит потенциальную ошибку.

  • Вы можете использовать findвезде, что сделает этот скрипт немного проще:

    for dir in `find. -maxdepth 1 -type d ! -name "." -printf "%f "`
    do
       echo $dir
    done
    

Не то чтобы все эти решения вызвали проблемы, если в именах есть каталоги с пробелами ().

0
28.01.2020, 02:15

Вы должны понимать, что выполняемая вами команда, а именно

for dir in `find. -maxdepth 1 -type d | grep -v \\.$ | awk -F'./' '{print $2}'`

Есть 2 уровня интерпретации котировок. На первом уровне, то есть на уровне командной строки, из которой выдается команда, текст под обратными кавычками `.... `сначала проверяется на наличие обратной косой черты и $переменных, как и в интерполяция котировок. Так как этот $сидит одиноко в конце, поэтому он не будет расширен. Хотя нет ничего плохого в том, чтобы сбежать от него.

Таким образом, останетсяgrep -v \\.$ ----> grep -v \.$

Теперь, когда этот шаг завершен, он должен быть передан подоболочке для выполнения. И в этой подоболочке команда grep -v \.$анализируется, а обратная косая черта удаляется, поэтому исполняемый файл grepполучает в конце этой фазы:grep -v.$

Теперь все непустые строки будут соответствовать этому шаблону и будут сгенерированы все непустые строки по той простой причине, что имена файлов не должны быть непустыми.

Таким образом, это означает, что все выходные данные findбудут выбраны, и, следовательно, обратное этому подразумевает, что никакие выходные данные из find не должны быть выбраны. Так что awk весь приоделся, но на самом деле ему некуда идти.

Решение:

Есть много вещей, которые вы можете предпринять, чтобы решить эту проблему.

  • Добавьте еще одну обратную косую черту в grep, чтобы:grep -v \\\.$Основываясь на том, что происходит на каждом этапе расширения котировок для этого сценария, убедитесь, что это исправление работает.
  • Используйте форму командной интерполяции $(), так как в этом формате цитирование начинается заново с $(), в отличие от формы обратного цитирования ``.
  • Используйте одинарные кавычки в grep, чтобы сделать его:grep -v '\.$'
  • Используйте классы символов, чтобы избежать расширения.:grep -v '[.]$'
  • Сделать все в findсамой команде:

find. -maxdepth 1 -type d ! -name. -exec sh -c '
   for d do printf "dir: %s\n" "${d:2}"; done
' sh {} +
1
28.01.2020, 02:15

Теги

Похожие вопросы