Подтвердить что ты не робот

Linux почему я не могу найти результат поиска в rm?

Извините, если это вопрос noobie, но я не могу найти хороший ответ.

Чтобы найти затем удалить что-то, я могу использовать

find . -name ".txt" -exec rm "{}" \;

Но почему я не могу просто передать результаты в rm как

find . -name ".txt" | rm 

как я бы подключил его к grep

find . -name ".txt" | grep a

Я где-то читал, что rm не принимает ввода от stdin, и поэтому я не могу его пропустить, но что это значит? Когда я набираю rm a.txt, он читает со стандартного ввода так же, как я могу grep правильно? Или есть разница между stdin и командной строкой. Помогите!

4b9b3361

Ответ 1

Чтобы расширить ответ на @Alex Gitelman: да, есть разница между "стандартным вводом" и командной строкой.

При вводе rm a.txt b.txt c.txt файлы, которые вы указываете после rm, называются аргументами и становятся доступными для rm через специальную переменную (называемую argv внутренне). С другой стороны, стандартный ввод данных относится к программе Unix, такой как файл с именем stdin. Программа может считывать данные из этого "файла" так же, как если бы он открывал обычный файл на диске и читал с него.

rm, как и многие другие программы, берет свои аргументы из командной строки, но игнорирует стандартный ввод. Вы можете направить все, что вам нравится; он просто выбросит эти данные. То, что xargs пригодится. Он считывает строки на стандартном вводе и превращает их в аргументы командной строки, поэтому вы можете эффективно передавать данные в командную строку другой программы. Это аккуратный трюк.

Например:

find . -name ".txt" | xargs rm
find . -name ".txt" | grep "foo" | xargs rm  

Обратите внимание, что это будет работать некорректно, если есть имена файлов, содержащие новые строки или пробелы. Чтобы обрабатывать имена файлов, содержащие новые строки или пробелы, вы должны использовать вместо этого:

find . -name ".txt" -print0 | xargs -0 rm

Это сообщит find о завершении результатов с нулевым символом вместо новой строки. Однако grep не будет работать по-прежнему. Вместо этого используйте это:

find . -name ".txt" | grep "foo" | tr "\n" "\0" | xargs -0 rm

На этот раз tr используется для преобразования всех новых строк в нулевые символы.

Ответ 2

"почему я не могу передать результат поиска в rm?"

Когда вы подключаете что-то к программе, труба заменяет ввод клавиатуры. Имейте это в виду и задайте себе следующий вопрос: что бы rm сделать с клавиатурой? Удалить ваши нажатия клавиш? (немного глупо) Принятие интерактивного управления? (rm не является интерактивным, за исключением случаев, когда ему требуется подтверждение, которое действительно может быть задано трубой.)

На самом деле, когда rm уже запущен, вы не можете вводить команды, чтобы он удалял файлы.... так что вы не можете сделать это с помощью нити.

Если вы помните, что труба заменяет комбинацию клавиатуры/экрана, все сразу становится более логичным.

Теперь наоборот. Вы можете передать поток данных в grep. Означает ли это, что вы можете позволить grep считывать нажатия клавиш с клавиатуры в качестве входных данных?

ДА! На самом деле это то, что происходит изначально (без трубопроводов).

(b.t.w. обратите внимание, что вы не можете протрубить и не ввести аргумент поиска в grep)

Итак, теперь вы знаете, почему вы не можете подключиться к rm и ожидать, что он будет работать как аргумент командной строки.

tl; dr:

Анатомия программы в соответствии с философией UNIX:
файл, выход из файла, вход в клавиатуру, выход из экрана. → Труба заменяет только клавиатуру и экран.

Ответ 3

Труба посылает вывод первой команды на стандартный ввод секунды. rm не принимает стандартный ввод, поэтому вы не можете подключиться к нему. Вы можете использовать xargs для достижения такого же эффекта. Вы можете найти пример для xargs специально для вашего случая в странице man для xargs.

Ответ 4

Альтернатива без использования труб:

xargs rm -f <<< $(find . -name ".txt")