У меня есть некоторые папки с \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
всего одна папка?
У Вас есть только единственная команда там, таким образом, достаточно звонить 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
является самым соответствующим.
См. также
Вы можете использовать глобусы оболочки вместо find
:
for d in */ ; do
rmdir "$d"
done
Глобус оболочки */
соответствует всем папкам в текущем каталоге. Эта конструкция цикла for обеспечивает правильное разбиение слов автоматически.
Обратите внимание, что в зависимости от параметров вашей оболочки, это может игнорировать скрытые папки (имя начинается с.). Это поведение может быть изменено, чтобы соответствовать всем файлам для текущего сеанса, используя команду shopt -s dotglob
.
Также не забывайте всегда заключать в кавычки ваши переменные.
Оба ответа, записанные до сих пор, звонят 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
и **/*/
вместо */
как выше.