Достижение эффекта рекурсивного rmdir

Кажется, вы столкнулись с этой ошибкой:

https://lkml.org/lkml/2013/7/25/205

readline() inadvertently triggers an error recovery path when pastes larger than 4k overrun the line discipline buffer. The error recovery path discards input when the line discipline buffer is full and operating in canonical mode and no newline has been received. Because readline() changes the termios to non-canonical mode to read the line char-by-char, the line discipline buffer can become full, and then when readline() restores termios back to canonical mode for the caller, the now-full line discipline buffer triggers the error recovery.

When changing termios from non-canon to canon mode and the read buffer contains data, simulate an EOF push without the DISABLED_CHAR in the read buffer.

Importantly for the readline() problem, the termios can be changed back to non-canonical mode without changes to the read buffer occurring; ie., as if the previous termios change had not happened (as long as no intervening read took place).

Это было применено к ядру 10 декабря 2013 года, то есть ядру Linux версии 3.14. Вы используете более ранний дистрибутив Linux? Какой у тебя дистрибутив? Вы, вероятно, заменили свой реальный путь к файлу, поэтому я не могу считать символы. Не могли бы вы сделать:

for ((a=1; a<20; a++)); do echo "mv /long/path/to/file$a /longer/path/to/file$a"; done|wc -c

с вашими реальными путями -будет ли это что-то действительно близкое к 4k? Если это так, ошибка выше, вероятно, ваша.

Если да, то ответы на ваши вопросы:

  • это проблема, связанная с терминалом -(Xterm в моем случае )?

нет

  • копирование/вставка происходит через ssh :создает ли это проблему или усугубляет ее?

нет

  • это проблема, связанная с bash -на сервере?

Нет и да -это не ошибка в bash или какой-либо библиотеке, используемой bash. Ошибка в ядре.

  • Может быть, с другой оболочкой этого не произойдет?

Может быть, если оболочка не использует readline. Вроде зш.

Что касается связанных вопросов «как вставить несколько…», похоже, они не связаны с вашей проблемой. -Причина в том, что некоторые приложения могут читать вставленные вами команды. Наиболее известным примером этого является ssh, если вы запускаете команду ssh на удаленном сервере. Но, учитывая, что вы теряете только части строк, в вашем случае это маловероятно.

Второй вопрос 'Команды вставлены в терминал...' задан 25 сентября 2013 года, в то время патча не существовало, и это определенно выглядит как ошибка, которая у вас есть, и я подозреваю, что это ошибка ядра.

Как проверить наверняка? вставьте вывод uname -здесь.

0
18.12.2019, 15:45
2 ответа

GNU findи современные BSD find(, включая macOS ), имеют -deleteдействие, которое можно использовать для этого:

find. -type d -empty -delete

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

4
28.01.2020, 02:21

Вы можете использовать оболочку zsh для рекурсивного расширения аргумента в список (подкаталогов ), обратно -отсортированных по глубине; тогда rmdirможет обработать список по порядку. Это будет успешным только тогда, когда каждый каталог пуст, и выдаст предупреждения (и , а не удалить каталог ), если он не пуст. Это приведет к удалению пустых деревьев каталогов и выдаче предупреждений, когда каталоги не пусты.

Я позаимствовал функцию bydepthиз ответа Стефана здесь .

bydepth() REPLY=${REPLY//[^\/]}
rmdir **/(/O+bydepth)

Функция bydepth(относительно )устанавливает переменную REPLY, удаляя все не -прямые -символы косой черты. Эта строка REPLY затем используется функцией сортировки в квалификаторе glob O+, чтобы сначала упорядочить самые длинные -. Другой квалификатор glob — /, который выбирает только каталоги. Начальный подстановочный знак **/указывает zsh рекурсивно расширяться из текущего каталога.

Примеры прогонов:

$ : no files exist
$ mkdir -p a/b/c/d
$ find.
.
./a
./a/b
./a/b/c
./a/b/c/d
$ rmdir **/(/O+bydepth)
$ find.
.
$ 
$ : a file exists
$ mkdir -p a/b/c/d
$ touch a/b/c/somefile
$ find.
.
./a
./a/b
./a/b/c
./a/b/c/d
./a/b/c/somefile
$ rmdir **/(/O+bydepth)
rmdir: failed to remove ‘a/b/c/’: Directory not empty
rmdir: failed to remove ‘a/b/’: Directory not empty
rmdir: failed to remove ‘a/’: Directory not empty
$ find.
.
./a
./a/b
./a/b/c
./a/b/c/somefile
0
28.01.2020, 02:21

Теги

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