- Удаление всех файлов определённого типа в каталоге
- eye_ru
- Программер-наблюдатель
- Жестоко
- Re: Жестоко
- Спасибо!
- Re: Спасибо!
- xargs xargs xargs
- #!/bin/sh
- Рекурсивные операции с файлами в Linux
- Эпиграф
- chmod
- chown, chattr, chgrp
- rm, grep
- Прочие команды
- Заключение
- Постскриптум
- 2 комментария
- удаление файлов рекурсивно по маске с датой создания не позднее чем Х дней назад
- В тред врывается zsh, и выносит find
Удаление всех файлов определённого типа в каталоге
Есть каталог rare, в нём — куча подкаталогов и файлов. Нужно удалить все .m3u файлы. Делаю:
однако эта команда оставляет .m3u файлы, если в путях есть пробелы. Как заставить её обрабатывать пробелы?
Добавить двойные кавычки
Отличный совет, чувак. Я сейчас удалил половину каталога с музыкой.
Тогда экранированные двойные кавычки.
«Чуваком» будешь отца своего звать, а я тебе ответил на вопрос касательно классического метода, что решает эту задачу.
Не зря я написал именно так, как написал.
Ууу, кто-то только что спалил виртуала
Как такое могло получиться? Вы же не скопипастили «find -delete»?
/Music -type f -name «.txt» -delete в моем случае просто удалило все .txt файлы. С чего у вас удалилась музыка, если вы удаляете .m3u только?
Update:
Не нужно никаких костылей вроде xargs, find умеет удалять файлы с параметром -delete. Но для начала без него, проверьте, чтобы find искал все необходимые файлы, а потом уже дописывайте -delete, чтобы их удалить.
Источник
eye_ru
Программер-наблюдатель
Казалось бы, простая задачка. В Windows все просто — del /S smth.*, готово. Все файлы по маске smth.* в текущей директории и ниже будут удалены.
В Linux чуток сложнее.
Есть в Linux команда rm, но она дальше текущей директории не идет, зато прекрасно понимает полный путь к файлу, чем мы и воспользуемся.
Получить список всех файлов в текущей директории и поддиректориях по маске позволяет команда find -name «smth.*», ее вывод то нам и нужен. Осталось его перенаправить на вход команды rm. Это можно сделать 5ю способами:
xargs — формирует команду rm с аргументами считанными из стандартного ввода на которой мы подадим вывод команды find. нюансы использования описаны тут
1. find /path/to/dir -type f -name ‘smth*’ -print0 | xargs -0 rm;
exec — перенапаравляем вывод команды find на вход команды rm
2. find -name ‘smth.*’ -exec rm <> \;
UPD.
find — самый рульный способ
3. find -name ‘smth.*’ -delete;
UPD.
Способы подсказанные камрадом goodvin
4. find . -type f -name ‘smth*’ -delete
5. find . -type f -name ‘smth’ -exec rm -f — «<>» \;
Может есть ещё какие нибудь способы??
Жестоко
Re: Жестоко
> Может есть ещё какие нибудь способы?
См. -delete в `man find`.
что значит не работает?
права то на удаление есть?
какую ошибку пишет?
/test$ ls -R
.:
smth.123 smth.1231 smth.12311 -smth sd.1231 smth sd.1231 test
./test:
smth.123 smth.1231 smth.12311 -smth ss.111 smth ss.111
rr@pc:
/test$ rm -rvf *smth*
rm: invalid option — s
Try `rm ./’-smth sd.1231» to remove the file `-smth sd.1231′.
Try `rm —help’ for more information.
rr@pc:
/test$ ls -R
.:
smth.123 smth.1231 smth.12311 -smth sd.1231 smth sd.1231 test
./test:
smth.123 smth.1231 smth.12311 -smth ss.111 smth ss.111
rr@pc:
/test$ ls -R
.:
gentest.sh smth.123 smth.1231 smth.12311 -smth sd.1231 smth sd.1231 test
./test:
smth.123 smth.1231 smth.12311 -smth ss.111 smth ss.111
rr@pc:
/test$ rm — *smth*
rr@pc:
./test:
smth.123 smth.1231 smth.12311 -smth ss.111 smth ss.111
rr@pc:
У нас в конторе один из любимейших вопросов на собеседовании: как удалить сто тыщ мильонов файлов с заранее неизвестными названиями в одной директории?
Ответы типа «rm -f /path/to/dir/*» не подходят, поскольку звездочка преобразовывается в список файлов, удовлетворяющих wildmat’у (в данном случае — все файлы), а у шелла есть ограничение на размер командной строки.
Тот же результат будет у «find /path/to/dir -type f| xargs rm», поскольку, во-первых xargs преобразует весь stdin в одну строку (try: «find /tmp |xargs echo rm»), во-вторых, в именах файлов могут содержаться пробелы, которые не эскейпятся, в-третьих, названия файлов могут начинаться на -, из-за чего rm воспримет имя файла как неизвестную опцию и упадет. Ну и ограничение на длину команды никто не отменял. Первые три проблемы обходятся так:
find /path/to/dir -type f -print0 |xargs -0 rm —
Опция -print0 какбэ говорит команде find, что в качестве разделителей нужно использовать нулевой символ вместо перевода строки, а -0 указывает xargs, что разделитель — не пробел, а все тот же нулевой символ.
Поэтому правильным ответом считается команда
find . -type f -name ‘smth*’ -delete
или
find . -type f -name ‘smth’ -exec rm -f — «<>» \;
Ну или простенький цикл:
for f in «`find . -type f -name ‘smth*’`» ; do rm «$f»; done
по количеству кавычек в котором можно еще и определить степень знания особенностей использования шелла 🙂
Спасибо!
Re: Спасибо!
И, наконец, вот команда, которая будет выполнена для каждого файла:
-exec ln <> /var/www/obsolete \;
Здесь вы также должны дезактивировать знак ;, в противном случае командный процессор интерпретирует его как разделитель команд. Если вы забудете сделать это, find пожалуется, что для -exec отсутствует аргумент.
xargs xargs xargs
Спасибо за пост, узнал про xargs. Все ж намного проще:
find . -name .svn|xargs rm -rf
(удаление папки .svn во всех подпапках проекта)
Источник
#!/bin/sh
Линуксоид на велосипеде с моторчиком
Рекурсивные операции с файлами в Linux
Иногда возникает путаница между опциями -r и -R, каждая из которых в разных программах может означать рекурсивную обработку файлов в найденных каталогах. А может означать нечто совершенно противоположное или работать не так, как этого ожидал пользователь. Попробуем разобраться, в каких случаях что используется.
Эпиграф
— Это новый «Гарри Поттер». Я заказал версии для детей и взрослых, чтобы проверить, что в тексте нет различий.
Морис Мосс, The IT Crowd.
chmod
Ключ -r у chmod интерпретируется как «запретить всем чтение файла», а 755 в данном случае рассматривается как название файла, у которого изменяются права. Поскольку в подавляющем большинстве случаев файла с таким названием в текущей директории отсутствует, то команда возвращает ошибку.
chown, chattr, chgrp
У вышеперечисленных команд опция -r просто отсутствует. Для рекурсивной обработки директорий необходимо использовать опцию -R. Очевидно, так сделано из солидарности с «братской» командой chmod
Несмотря на то, что в странице документации cp из GNU coreutils сказано, что опции -r и -R равнозначны и означают рекурсивную обработку встречающихся директорий, опция -r, в отличие от -R, не соответствует стандарту POSIX и ее указание может повлечь за собой неожиданные последствия в случае, если очередной копируемый объект является чем-то отличным от обычного файла или директории (например, символической ссылкой, fifo или сокетом). В таких случаях некоторые реализации cp просто копируют содержимое ссылки/fifo, тогда как при -R такие объекты пересоздаются заново. Раньше такое поведение было присуще GNU cp, о чем до сих пор имеется свидетельство в русском man cp. Что касается более правильных (чем Linux) систем, то, например, в BSD-версии cp опция -r работает в «режиме совместимости», т.е. не создает символическую ссылку заново, а копирует содержимое в файл с тем же именем.
Ключ -r команды ls означает «обратный порядок сортировки»
Правильно:
rm, grep
Зато в следующих случаях употребление -r/-R равнозначно:
Что касается grep, то, во-первых, обе опции не соответствуют POSIX (но, похоже, присутствуют во всех реализациях) Во-вторых, иногда возникает путаница между опциями -i (игнорировать регистр) и -I (пропускать двоичные файлы). Но это уже тема для другого разговора 🙂
Прочие команды
Поскольку команд, в том или ином виде поддерживающих рекурсивную обработку каталогов, набралось довольно много, то я попробовал свести их в одну таблицу.
команда | -r | -R |
---|---|---|
chacl | рекурсия | удаление ACL только с файлов |
setfacl | не поддерживается | рекурсия |
cvs | номер ревизии | рекурсия |
diff | рекурсия | не поддерживается |
gzip/gunzip | рекурсия | не поддерживается |
zip | рекурсия | рекурсия, начиная с текущей директории (см. man zip, там есть существенная разница в обработке -r и -R) |
rsync | рекурсия | использование относительных путей |
wget | рекурсия | указывает список отвергаемых шаблонов |
Заключение
Как видно, в большинстве случаев для указания рекурсии используется опция -r в нижнем регистре, в противовес стандартным утилитам, для которых характерно все же -R. Поэтому совет один: в случае сомнения смотрите в man, там все написано 🙂
Постскриптум
По абзацу про cp видно, что русская документация в некоторых дистрибутивах (не будем показывать пальцем на Debian и Ubuntu) не соответствует реальному положению дел. В частности, несмотря на то, что в jaunty используется GNU coreutis 6.10, русский man описывает cp версии 4.1. Желающие могут самостоятельно сравнить свою версию man 1 cp с локализованной. Другими словами, русская страница документации cp в силу своей древности вводит пользователя в заблуждение, т.е. врёт. По этой причине я рекомендую сделать apt-get remove manpages-ru.
2 комментария
- Comment by anon :
> По этой причине я рекомендую сделать apt-get remove manpages-ru
Плюсую. Помню как потерял с час времени, из за феерично переведенного мана:
If from is not NULL, and the underlying protocol provides the source address, this source address is filled in.
Если параметр from не равен NULL, а сокет не является ориентированным на соединения, то адресотправителя в сообщении не заполняется.
scp неплохо было бы упомянуть. Нигде проблем с -r/-R не испытывал, только в scp почему-то постоянно пишу -R.
Источник
удаление файлов рекурсивно по маске с датой создания не позднее чем Х дней назад
задача: удалить все файлы в категории и ее подкатегориях, которые попадают под маску, но при этом созданы не позднее чем 3 дня назад (т.е. оставим все самые свежие — за последние три дня).
удаление просто по маске: find PATH -name «*.FILE_EXT» -exec rm <> \;
а как удалить с учетом требования по дате?
atime, mtime насчет «созданных» — не знаю.
find -ctime +DAYS PATH -name «*.FILE_EXT» -exec rm <> \;
DAYS — кол-во дней PATh — путь к корневой директории *.FILE_EXT — маска для файла
удалит все файлы с датой создания старше 3-х дней по заданной маске
Это делается проще: «-delete». Если ты этого не знал, то ман не прочитал, поэтому в первую очередь советую его сначала таки прочитать, а потом бежать на лор. Конкретно понадобятся опции -*time, -newer, -newer*.
удалит все файлы с датой создания старше 3-х дней
Всё-таки ман не прочитал. А там белым по чёрному написано:
-ctime n File’s status was last changed n*24 hours ago.
Это не дата создания.
-delete будет работать быстрее? если да, насколько?
я в курсе, в данном случае нужно было найти файлы именно созданные от нужной даты. в случае проверки на изменения -mtime
А просто взять и проверить лень? В случае использования «-delete» find сам сразу делает unlink(), а в случае «-exec rm» для каждого файла будет вызываться fork(), exec(), создастся новый процесс rm, который получит имя файла из командой строки, распарсит параметры и в конце концов сделает unlink. Конечно, первое быстрее, чем второе.
BTW, ещё можно так: «-exec rm ‘<>‘ +», тогда в командную строку rm передадутся сразу несколько путей и лишних процессов будет меньше, чем при «-exec rm ‘<>‘ \;».
Ты же понимаешь, что это зависит от множества факторов, и на разных компьютерах разница будет разной?
в данном случае нужно было найти файлы именно созданные от нужной даты
Ну так анонимус всё правильно говорит, потому что ctime — это не дата создания. Он может меняться. Не можешь прочитать ман, так прочитай Википедию:
-ctime — время последнего изменения владельца или прав доступа к файлу.
В тред врывается zsh, и выносит find
man я читала.
в моем случае ни права, ни группа\пользователь не меняются, и это самое близкое что я нашла к дата_создания (мне не нужна дата модификации).
если вы знаете способ сравнивать именно _дату_создания_, напишите пожалуйста
если вы знаете способ сравнивать именно _дату_создания_, напишите пожалуйста
Например, параметр «-newerBt». В данном случае будет что-то типа:
find «$path» ! -newerBt ‘3 day ago’ -delete
Но на моей ФС (ext4) это не работает — похоже, что она вообще не сохраняет дату создания. Если это так, то проблему в исходном виде решить не получится и придётся использовать ctime. Возможно, на других ФС будет работать и вариант с -newerBt.
на моей также не хранит, поэтому я и решила использовать ctime, как наиболее близкую к дате создания.
дата_создания (мне не нужна дата модификации)
Часто модификация приводит к тому, что исходный файл удаляется, вместо него остается измененная копия (inode соотвественно меняется).
vcs развернуть и смотреть дату создания его средствами не судьба?
Источник