(on Wikipedia)
http://www.gnu.org/software/findutils/
"The GNU Find Utilities" is one of those packages that's installed everywhere. find
is one of those programs everyone ends up using and ends up being horrified at.
-
aka GNU Find Utilities
See also:
--
- 2020-01-01 - 4.6.0+git+20190209-2 on Debian 10.1.0-amd64-xfce-CD-1 (10)
- 2020-01-01 - 4.6.0+git+20161106-2 on Debian 9.9.0-i386-xfce-CD-1 (9.11)
- 2018-04-13 - 4.4.2-9+b1 on Devuan-1.0.0-jessie-i386-DVD
- 2016-04-01 - 4.4.2 on Slackware 14.1
- 2016-03-26 - 4.4.2 on Lubuntu 14.04.4 LTS
- 2007-07-24 - 4.2.27 on (distribution not recorded)
-
It has been previously used, but no notes were taken.
- 1 2016-03-26 - 4.4.2
- 2 2007-07-24 - 4.2.27
- 3 Usage and troubleshooting
- 3.1 Correct permissions
- 3.2 Delete files
- 3.3 Delete empty files
- 3.4 find directories
- 3.5 find directories, excluding some
- 3.6 building one flat symlink directory from a tree
- 3.7 finding files of a certain time
- 3.8 find based on size
- 3.9 Finding content in files
- 3.10 Finding content in files, excluding several directories
- 3.11 Find broken symlinks
- 3.12 Find hard links
- 3.13 Notes utility
- 3.14 using
-exec
multiple times - 3.15 resolving
argument list too long
- 3.16 Untested - Rename files
- 3.17 Use variables within
- 4 Remaining questions
2016-03-26 - 4.4.2 ∞
4.4.2-7
This came installed with Lubuntu.
It's as unusable as any GNU software can be expected to be. Very powerful. Non-obvious to an extreme. Poorly documented. The usual.
Here are some fun notes, just to show that find can actually be useful in spite of itself.
Various versions of these can be found on https://github.com/spiralofhope/shell-random/tree/master/README.markdown
2007-07-24 - 4.2.27 ∞
-
Find doesn't look in the current directory *first*?! sigh..
Usage and troubleshooting ∞
Correct permissions ∞
\find . -name '*' -type d -exec \chmod 770 {} ; \find . -name '*' -type f -exec \chmod 660 {} ;
Or perhaps you want to be more specific:
\find . -name '*' -type d -exec \chmod 755 {} ; \find . -name '*' -type f -exec \chmod 644 {} ; \find -L ./directory/location/ -name 'filename*.ext' -exec command {} ;
But perhaps you want to be super-optimized!
\find -type f -not -perm 644 -exec chmod 644 {} \; \find -type d -not -perm 755 -exec chmod 755 {} \;
removing executability for all files ∞
\find /path/to/files/ -type f -name '*' -exec \chmod -x {} ;
Delete files ∞
Delete temporary files:
\find -L ./ -name '*~' -exec \rm {} ; \find -L ./ -name '.*~' -exec \rm {} ;
You'll notice it does not need to rm -f
.
Delete empty files ∞
\find -type f -empty -delete
or:
\find -type f -empty -exec \rm {} ;
or maybe:
find -L ./ -name '*' -empty -exec \rm {} ;
find directories ∞
\find ./ -name '*' -type d -exec \chmod 0700 {} ;
See also tree.
find directories, excluding some ∞
find ./ -name '*' ( -name DIR1 -o -name DIR2 -o -name DIR3 ) -prune -o -type d -print
building one flat symlink directory from a tree ∞
Any file that is mentioned here is a duplicate filename.
\find /path/to/source/ -type f -name '*' -exec \ln --symbolic {} --target-directory=/path/to/target/ ;
finding files of a certain time ∞
\find . -mmin +4736 -mmin -4742
I think this summarizes find pretty well. Standard convoluted GNU software.
find based on size ∞
- find empty files
\find -type f -empty
.. but you can also do:
\find -type f -size 0
- Find large files
\find -type f -size +100000k \find -type f -size +100M
Finding content in files ∞
The simple way:
\grep -ri 'background' /path/to/filename.ext
Finding files in a tree:
\find -type f -name '*' -print0 | xargs -r0 grep -Fi 'example string'
Maybe to deal with files with spaces, I should do:
\find -type f -name '* *' -print0 | xargs -r0 grep -Fi 'example string'
An old note said:
\find . -type f -exec \grep "string_to_look_for" {} +
Finding content in files, excluding a directory ∞
\find ./ -path ./path -prune -o -type f -name '*' -print0 | xargs -r0 grep -Fi 'example string'
Finding content in files, excluding several directories ∞
Newest:
\cd /path/to/use \find -maxdepth 1 -type d \ -not -path './to_exclude_1/*'
New hotness:
\cd /path/to/use \find -maxdepth 1 -type d ! -name 'to_exclude_1' ! -name 'to_exclude_2' ! -name .
The final .
can be used to also exclude the current directory.
Old insanity:
\find / -path '/path/to/exclude_1' -prune -o -path '/path/to/exclude_2' -prune -o -type f -name '*' -print0 | xargs -r0 grep -Fi 'contents'
Find broken symlinks ∞
Find hard links ∞
Notes utility ∞
Chew on this one - open all the notes for projects. If the file isn't there, make it.
This can get complex. I've done it in a way that'll mess up syntax highlighting, but it'll at least let you format things in an expected way. Note that the formatting got mangled by WordPress, but you can further-indent lines as you see fit.
See projects.sh (and it's edit history for the simpler version)
using -exec
multiple times ∞
\find . -maxdepth 1 -type d \ -exec \echo {} \; \ -exec \echo {} \;
resolving argument list too long
∞
With rm
, find
, etc.
Untested - Rename files ∞
This might have been tested a very long time ago (like 2008) but I don't understand it at a glance and cannot recommend it.
These will take a while to run on large directories because it is pre-building the list to use.
0=$IFS ; IFS=$(echo -en "\n\b") ; for f in `find -name *.JPG`; do rename .JPG .jpg "$f" ; done ; IFS=$0
Preserve .JPG
if found in the middle of filenames.
0=$IFS ; IFS=$(echo -en "\n\b") ; for f in `find -regex '.*\.JPG$'`; do rename .JPG .jpg "$f" ; done ; IFS=$0
Use variables within ∞
You might think to do:
\touch 'hello_world_replacement' variable=text \rename -n 's/hello_world/$variable/' * # => # Global symbol "$variable" requires explicit package name (did you forget to declare "my $variable"?) at (user-supplied code).
.. but that will not work. Instead, use the \Q$ENV{variable}\E
construct:
\touch 'hello_world_replacement' export variable=text \rename -n 's/hello_world/\Q$ENV{variable}\E/' * # => rename(hello_world_replacement, text_replacement)
Remaining questions ∞
- How do I make
find
look in the current directory first? -
TODO - Do some exploration on using a pipe with find. I have one decent lead:
find ./ -name lea_01.001 -print -exec sh -c 'CEOS $1 | grep -i radio' {} {} \;
Can -exec
use a function? ∞
Short answer: You can't. Put your function in a script and then -exec
it.
But you can sortof do it like this:
\find . -name '* *' -type f \ -exec \echo "{}" \; \ -exec \echo "{}" \; \
only display filenames ∞
\find . -iname "*search string*" -exec basename {} \; # Perhaps like so: \find . -iname "*search string*" -exec basename {} \; | \sort
find multiple extensions ∞
\find \ . \ -type f \ \( \ -iname "*.markdown" \ -o -iname "*.txt" \ \)
Last updated 2022-09-28 at 16:22:56
referencing "argument list too long"
fixed the structure, and cleaned up some items.
ported remaining notes
cleaned some things up a little more
examples:
- only display filenames
- using variables
Removed the projects code; I don't think it works anyway.
- pushed a couple of items into shell scripts to workaround a blogtext bug
- decrufted a bit
Finding multiple extensions is really this hard.
Fucking findutils.