Find: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(10 intermediate revisions by the same user not shown)
Line 13: Line 13:
=Other Arguments=
=Other Arguments=


==-print==
==<tt>-print</tt>==


It prints the pathname of  the current file to standard output
It prints the pathname of  the current file to standard output
==<tt>-print0</tt>==
This primary always evaluates to true.  It prints the pathname of the current file to standard output, followed by an ASCII NUL character (character code 0). Useful [[#Iterating_over_find_Results_in_Scripts|when iterating over the result of find]].


=Target Type=
=Target Type=
Line 98: Line 102:
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
find . -exec command {} \;
find . -exec command {} \;
</syntaxhighlight>
<syntaxhighlight lang='bash'>
find mydir -name '*.mp3' -exec sh -c '
    echo "Playing ${1%.mp3}"
    play "$1"
  ' sh {} \;
</syntaxhighlight>
</syntaxhighlight>


=Iterating over <tt>find</tt> Results in Scripts=
=Iterating over <tt>find</tt> Results in Scripts=
<br>
<br>
<font color=darkkhaki>TODO: reconcile and merge with [[Bash Listing Files in a Directory and Testing whether Specific Files Exist in Directories]].</font>
<br>
<br>
<syntaxhighlight lang='bash'>
while IFS= read -r -d '' file
do
  (( count++ ))
  echo "Playing file no. $count"
  play "$file"
done <  <(find mydir -mtime -7 -name '*.mp3' -print0)
echo "Played $count files"
</syntaxhighlight>
Borrowed from https://github.com/koalaman/shellcheck/wiki/SC2044
⚠️ The following is a less safe form, it is frowned upon by spellcheck: "For loops over find output are fragile. Use find -exec or a while read loop." See: {{External|https://github.com/koalaman/shellcheck/wiki/SC2044}}
This protects against paths with spaces in them:
This protects against paths with spaces in them:
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
declare -a files
declare -a files
IFS="$(printf '\t\n')"
IFS="$(printf '\n\r')"
for i in $(find "${user_level_toolbox_app_dir}" -name .history.json -type f); do
for i in $(find "${user_level_toolbox_app_dir}" -name .history.json -type f); do
   history_files+=("${i}")
   files+=("${i}")
done
done
IFS="$(printf ' \t\n')"
IFS="$(printf ' \t\n\r')"
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 18:54, 14 August 2023

Internal

Numeric Arguments

All numeric arguments are interpreted as follows:

+n for greater than n
n for exactly n
-n for less than n

Other Arguments

-print

It prints the pathname of the current file to standard output

-print0

This primary always evaluates to true. It prints the pathname of the current file to standard output, followed by an ASCII NUL character (character code 0). Useful when iterating over the result of find.

Target Type

find . -type <type-identifier>

where the type identifier can be:

  • f regular file
  • d directory
  • l symbolic link
  • b block special
  • c character special
  • p FIFO
  • s socket

Case Insensitive Search

find . -iname ...

Control Descend Depth

The upper and lower limit of the descend depth can be controlled with -mindepth and -maxdepth, as follows:

find . -mindepth n

Configure find to apply tests and action at levels equal or deeper than n. -mindepth 1 processes the content of the directory specified as argument and recursively the content of its sub-directories.

find . -maxdepth n

Configure find to descend at most n directory levels below the command line arguments. -maxdepth 0 limits the whole search to the command line arguments.

In order to access directory between an upper and lower depth limit, both -mindepth and -maxdepth should be used.

Time Constraints

For interpretation of numeric arguments (+-n), see: Numeric Arguments.

Time flags:

  • -amin n - file was accessed n minutes ago.
  • -anewer file - file was accessed more recently than file was modified.
  • -atime n - file was accessed n * 24 hours ago. When find figures out how many 24-hour periods ago the file was last accessed, the fractional part is ignored, so to match -atime + 1, a file has to have been accessed at least two days ago.
  • -cmin n - file's status was last changed n minutes ago
  • -cnewer file
  • -ctime n - file's status was last changed n*24 hours ago. See the comments for -atime to understand how rounding affects the interpretation of file status change times.
  • -mmin n -
  • -mtime n - file's data was last modified n*24 hours ago. See the comments for -atime to understand how rounding affects the interpretation of file modification times.

Find all files modified less that 2 days ago

find . -mtime -2

-name Patterns

A pattern for file names with specific characters on specific positions can be specified with [...]:

find . -name *.[jw]ar

looks for *.jar and *.war.

For more complex expression syntax, see Expressions below.

Mac Detail

On Mac, the pattern must be specified between quotes:

find . -name "*.something"

Expressions

"-name pattern" is an expression. Multiple expressions can be combined using the operators -not, -and and -or.

Example:

find . -name '*.jar' -and -not -name '*-source.jar'

Filtering "." out from the directory list:

find . -type d -not -name '.'

Exec

find . -exec command {} \;
find mydir -name '*.mp3' -exec sh -c '
    echo "Playing ${1%.mp3}"
    play "$1"
  ' sh {} \;

Iterating over find Results in Scripts



TODO: reconcile and merge with Bash Listing Files in a Directory and Testing whether Specific Files Exist in Directories.


while IFS= read -r -d '' file
do
  (( count++ ))
  echo "Playing file no. $count"
  play "$file"
done <   <(find mydir -mtime -7 -name '*.mp3' -print0)
echo "Played $count files"

Borrowed from https://github.com/koalaman/shellcheck/wiki/SC2044


⚠️ The following is a less safe form, it is frowned upon by spellcheck: "For loops over find output are fragile. Use find -exec or a while read loop." See:

https://github.com/koalaman/shellcheck/wiki/SC2044

This protects against paths with spaces in them:

declare -a files
IFS="$(printf '\n\r')"
for i in $(find "${user_level_toolbox_app_dir}" -name .history.json -type f); do
  files+=("${i}")
done
IFS="$(printf ' \t\n\r')"