- Exclude list of files from find
- 7 Answers 7
- Команда find Linux
- Поиск
- -name: Поиск по имени
- Поиск по расширению
- -not: обратное условие
- Несколько условий вместе
- -o: Логическое или
- Найти и скопировать
- Поиск по типу
- Уровни вложенности
- Поиск по размеру файла
- Поиск по началу имени файла
- Поиск по части имени файла
- -perm: поиск по правам доступа
- -path: поиск путей
- -prune: ограничить глубину
- Исключить директорию из поиска
- Добавить исключения директорий в find
Exclude list of files from find
If I have a list of filenames in a text file that I want to exclude when I run find , how can I do that? For example, I want to do something like:
find /dir -name "*.gz" -exclude_from skip_files
and get all the .gz files in /dir except for the files listed in skip_files. But find has no -exclude_from flag. How can I skip all the files in skip_files ?
7 Answers 7
I don’t think find has an option like this, you could build a command using printf and your exclude list:
find /dir -name "*.gz" $(printf "! -name %s " $(cat skip_files))
Which is the same as doing:
find /dir -name "*.gz" ! -name first_skip ! -name second_skip . etc
Alternatively you can pipe from find into grep :
find /dir -name "*.gz" | grep -vFf skip_files
Does this work for inclusions as well? I just tested and I got nothing: included_paths=(«./.aws/*» «./.bash_env.m4») && find . -type f -name ‘*.m4’ \( -path «$» $(printf » -or -path ‘%s'» «$») \) . When I directly put in the paths into the find command, it does work.
This is what i usually do to remove some files from the result (In this case i looked for all text files but wasn’t interested in a bunch of valgrind memcheck reports we have here and there):
find . -type f -name '*.txt' ! -name '*mem*.txt'
Example for if you need to ignore multiple filenames / patterns: find . -type f ! -name ‘.foo’ ! -name ‘.bar’ .
find /dir \( -name "*.gz" ! -name skip_file1 ! -name skip_file2 . so on \)
find /var/www/test/ -type f \( -iname "*.*" ! -iname "*.php" ! -iname "*.jpg" ! -iname "*.png" \)
The above command gives list of all files excluding files with .php, .jpg ang .png extension. This command works for me in putty.
PuTTY is a remote terminal (usually using SSH) — whether it works will very much depend on what you’re SSH’ing into.
Josh Jolly’s grep solution works, but has O(N**2) complexity, making it too slow for long lists. If the lists are sorted first (O(N*log(N)) complexity), you can use comm , which has O(N) complexity:
find /dir -name '*.gz' |sort >everything_sorted sort skip_files >skip_files_sorted comm -23 everything_sorted skip_files_sorted | xargs . . . etc
man your computer’s comm for details.
This solution will go through all files (not exactly excluding from the find command), but will produce an output skipping files from a list of exclusions. I found that useful while running a time-consuming command ( file /dir -exec md5sum <> \; ).
- You can create a shell script to handle the skipping logic and run commands on the files found (make it executable with chmod , replace echo with other commands):
$ cat skip_file.sh #!/bin/bash found=$(grep "^$1$" files_to_skip.txt) if [ -z "$found" ]; then # run your command echo $1 fi
- Create a file with the list of files to skip named files_to_skip.txt (on the dir you are running from).
- Then use find using it:
find /dir -name "*.gz" -exec ./skip_file.sh <> \;
Working out
this will fail if any of the filenames has a space in it that is unquoted (which it must be if sharing the exclusion list with another utility that expect it that way.)
Команда find Linux
find это мощный инструмент для работы с файлами.
С его помощью можно задавать различные составные условия для дальнейших действий над файлами.
Часто ипользуется как первый шаг перед копированием, перемещением, удалением, изменением файлов, соответсвующих определённым условиям.
В этой статье вы можете познакомится с основами применения find. Про применение find совместно с grep , sed , xargs и другими утилитами вы можете прочитать в статье «Продвинутые методы работы с find»
Поиск
Найти и вывести на экран все файлы в директории
find
find .
find . -print
-name: Поиск по имени
Найти по полному имени в текущей директории
find . -name ‘heihei.log‘
find . -iname ‘heihei.log‘
Поиск по расширению
Найти по расширению файла с помощью wildcard *
Ищем в /usr/share/doc все pdf файлы
find /usr/share/doc -name ‘*.pdf‘
-not: обратное условие
Найти в текущей директории все файлы кроме php
find . -not -name ‘*.php‘
find . ! -name ‘*.php‘
Несколько условий вместе
Найти все файлы, которые начинаются с log но не имеют расширения .txt
find . -name «log*» ! -name ‘*.txt‘
-o: Логическое или
Найти либо .html либо .php файлы
find . -name ‘*.html‘ -o -name ‘*.php‘
Найти и скопировать
Найти и сразу скопировать в текущую директорию
find /usr/share/doc -name ‘*.pdf‘ -exec cp <> . \;
Найти в текущей директории
Удалить из текущей директории
find -name ‘*.pdf‘ -delete
Поиск по типу
Чтобы найти только файлы определённого типа выполните find с опцией type.
Например, что найти все ссылки в директории /etc
Подробнее о файлах в Linux читайте в статье «Типы файлов в Linux»
Уровни вложенности
Найти все ссылки только на верхнем уровне вложенности
find /etc -maxdepth 1 -type l
Поиск по размеру файла
Filesystem Size Used Avail Use% Mounted on /dev/sda1 1014M 194M 821M 20% /boot
Найти обычные файлы определённого размера
Чтобы найти обычные файлы нужно использовать -type f
find /boot -size +20000k -type f
find: ‘/boot/efi/EFI/centos’: Permission denied find: ‘/boot/grub2’: Permission denied /boot/initramfs-0-rescue-389ee10be1b38d4281b9720fabd80a37.img /boot/initramfs-3.10.0-1160.el7.x86_64.img /boot/initramfs-3.10.0-1160.2.2.el7.x86_64.img
Файлы бывают следующих типов:
— : regular file
d : directory
c : character device file
b : block device file
s : local socket file
p : named pipe
l : symbolic link
find /boot -size +10000k -type f
find: ‘/boot/efi/EFI/centos’: Permission denied find: ‘/boot/grub2’: Permission denied /boot/initramfs-0-rescue-389ee10be1b38d4281b9720fabd80a37.img /boot/initramfs-3.10.0-1160.el7.x86_64.img /boot/initramfs-3.10.0-1160.el7.x86_64kdump.img /boot/initramfs-3.10.0-1160.2.2.el7.x86_64.img /boot/initramfs-3.10.0-1160.2.2.el7.x86_64kdump.img
То же самое плюс показать размер файлов
find /boot -size +10000k -type f -exec du -h <> \;
find: ‘/boot/efi/EFI/centos’: Permission denied find: ‘/boot/grub2’: Permission denied 60M /boot/initramfs-0-rescue-389ee10be1b38d4281b9720fabd80a37.img 21M /boot/initramfs-3.10.0-1160.el7.x86_64.img 13M /boot/initramfs-3.10.0-1160.el7.x86_64kdump.img 21M /boot/initramfs-3.10.0-1160.2.2.el7.x86_64.img 14M /boot/initramfs-3.10.0-1160.2.2.el7.x86_64kdump.img
Поиск по началу имени файла
Обратите внимание, что в find, в отличие от grep , ставить перед началом названия никаких символов не нужно.
find -name ‘topb*‘
Поиск по части имени файла
Найти в проекте topbicyle все директории с qa в названии
find topbicycle/ -name ‘*qa*‘ -type d
-perm: поиск по правам доступа
find . -type f -perm 0600
find . -type f ! -perm 0600
-path: поиск путей
Если мне нужно посмотреть содержимое директорий /code/php и /code/python
Пример укороченного результата
-prune: ограничить глубину
С помощью path можно посмотреть содержимое всех поддиректорий code на букву p /code/p*
Если нужно посмотреть только поддиректории верхнего уровня — используется -prune
find . -path «./code/p*» -prune
Получили только поддиректории без их содержимого
Исключить директорию из поиска
Из предыдущего параграфа понятно, что с помощью prune можно исключить директорию из поиска.
Пример: найти в ./code все файлы, заканчивающиеся на index.php но проигнорировать поддиректории на p, то есть в директориях python и php не искать.
find ./code -path «./code/p*» -prune -false -o -name «*index.php»
./code/js/errors/index.php ./code/js/index.php ./code/c/index.php ./code/cpp/index.php ./code/go/pointers/index.php ./code/go/declare_variable/index.php ./code/go/constants/index.php ./code/go/index.php ./code/java/index.php ./code/dotnet/index.php ./code/ruby/index.php ./code/theory/index.php ./code/index.php
-false нужен чтобы не выводить проигнорированные директории.
Ещё один способ исключить директорию из поиска
find ./code -name «*.php« -not -path «./code/p*»
Добавить исключения директорий в find
Самое простое, если в именах директорий в корне нет пробелов, то можно как-то так:
find $(ls / | grep -Ev '^(dev|proc|sys|run)$') -depth -exec stat .
Если подзакладываться на пробелы, то можно что-то такое соорудить:
ls / | grep -Ev '^/(dev|proc|sys|run)$' | while read d; do find "$d" -depth -exec stat . ; done
Менее эффективный вариант, но учитывающий пробелы (и переводы строк) и ограничивающийся одним find ‘ом:
find / -! \( -path '/dev/*' -o -path '/proc/*' . \) -depth -exec stat .
Для исключения каталога и его вложения из поиска и вывода программой find следует указывать параметры поиска -not -path ‘/path*’ , если нужно оставить каталог но исключить его содержимое, то указываем ‘/path/*’ , если нужно убрать каталог, но оставить содержимое, то указываем ‘/path’
Важно: При исключении каталога и его содержимого ‘/path*’ — дополнительно могут быть исключены каталоги по маске, т.е. если прописать /work* , то будут исключены /work /workdir /working и т.д.
Дополнительно, внешнюю программу stat можно не использовать, данные можно получить стандартным параметром -printf
find / \ -not -path '/dev*' \ -not -path '/proc*' \ -not -path '/sys*' \ -not -path '/run*' \ -printf '%m %U %G %p\n'
find / -not \( -path '/dev*' -o -path '/proc*' -o -path '/sys*' -o -path '/run*' \) -printf '%m %U %G %p\n'