для цикла в папках с \n символом на их имена

У меня есть некоторые папки с \n изобразите его их имена.

например:

$ ls
''$'\n''Test'

Это, относятся к папке с Тестовым именем и пустой строкой перед ее именем.

Таким образом, когда я запускаю некоторые скрипты как это в его родительском каталоге:

while IFS= read -r d; do 
    rmdir $d
done < <(find * -type d)

Это показывает:

rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory

Поскольку это работает дважды, однажды на \n и другой на Test, потому что имя папки имеет две строки.

Таким образом, как я могу решить эту проблему, таким образом, что, сценарий знает \nTest всего одна папка?

9
задан 4 June 2018 в 15:21

3 ответа

У Вас есть только единственная команда там, таким образом, достаточно звонить find с -exec вызов флага rmdir:

find -depth -type d -exec rmdir {} \;

Или используйте -delete опция как в find -type d -delete, но это не будет работать с непустыми каталогами. Для этого Вам также будет нужно -empty флаг. Отметьте также, -delete подразумевает -depth таким образом, это может быть пропущено. Таким образом другая жизнеспособная альтернатива, которая сохраняет все как один процесс:

find -type d -empty -delete

Если каталог, не пустой, использовать rm -rf {} \;. Изолировать только каталоги с \n в имени файла мы можем объединить ANSI-C удара, заключающий в кавычки $'...' с -name опция:

find  -type d -name $'*\n*' -empty -delete

POSIX-ly, мы могли обработать его этот путь:

find -depth  -type d -name "$(printf '*\n*' )" -exec rmdir {} \;

Стоит упомянуть это, если Вашей целью является удаление каталогов, то -delete достаточно, однако если Вы хотите выполнить команду на каталоге затем -exec является самым соответствующим.

См. также

12
ответ дан 23 November 2019 в 04:46

Вы можете использовать глобусы оболочки вместо find:

for d in */ ; do 
    rmdir "$d"
done

Глобус оболочки */ соответствует всем папкам в текущем каталоге. Эта конструкция цикла for обеспечивает правильное разбиение слов автоматически.

Обратите внимание, что в зависимости от параметров вашей оболочки, это может игнорировать скрытые папки (имя начинается с.). Это поведение может быть изменено, чтобы соответствовать всем файлам для текущего сеанса, используя команду shopt -s dotglob.

Также не забывайте всегда заключать в кавычки ваши переменные.

10
ответ дан 23 November 2019 в 04:46

Оба ответа, записанные до сих пор, звонят rmdir однажды на каталог, но как rmdir может взять несколько аргументов, интересно: Нет ли более эффективный путь?

Можно было просто сделать

rmdir */

и это - определенно самый легкий и самый эффективный путь, но он может бросить ошибку в случае многих каталогов (см. то, Что максимальная длина параметров командной строки в терминале гнома?). Если Вы хотите, чтобы этот подход работал рекурсивно, включите globstar опция оболочки с shopt -s globstar и используйте **/*/ вместо */.

С GNU find (и если мы не просто хотим использовать -delete), мы могли сделать

find -depth -type d -exec rmdir {} +

какой builts командная строка “почти таким же способом, который xargs создает его командные строки” (man find). Замена -depth для -maxdepth 1 если Вы не хотите, чтобы это работало рекурсивно.

Одна треть и блестящий путь IMO объяснены steeldriver в этом ответе:

printf '%s\0' */ | xargs -0 rmdir

Это использует встроенную оболочку printf для создания разграниченного нулем списка аргументов этот список затем передается по каналу к xargs который звонит rmdir точно так же часто по мере необходимости. Можно заставить его работать рекурсивно с shopt -s globstar и **/*/ вместо */ как выше.

6
ответ дан 23 November 2019 в 04:46

Другие вопросы по тегам:

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