cli - find

最後更新: 2024-09-27

目錄

  • 常用 Opts
  • Size
  • Type
  • Permission
  • Depth
  • regex
  • path
  • Symbolic
  • Action - prune
  • Action - exec
  • find 與 xargs
  • A pipe "|" in linux 's find -exec command
  • 應用

 


介紹

 

The "find" searches the directory tree rooted at each given starting-point

evaluating the given expression from left to right

If no starting-point is specified, `.' is assumed

Note that the pattern match test applies to the whole file name, starting from one of the start points named

 

 


常用 Opts

 

Time

-mtime

Unit                  # n x 24 小時

  • +n                    # for greater than
  • -n                     # for less than n
  • n                      # n 當天 24 小時內的 file

i.e.

# n*24 hours ago

-mtime n

# file less than 24 hours ago

find $HOME -mtime 0

-mmin

File's data was last modified n minutes ago.

i.e.

find $LockFile -mmin +2

P.S.

雖然 ls 時是看不到秒數, 但秒數依然計算在內, 所以 17:50 未必出現 17:48 的 Dir

-newer file

File was modified more recently than file.

-newerXY reference

i.e.

-newermt "2021-08-04"

  • m   The modification time of the file reference
  • t     "reference" is interpreted directly as a time

Time specifications are interpreted as for the argument to the -d option of GNU `date`
(i.e. "2004-02-29 16:21:42")

i.e. 有某段時間修改過的 file

# -ls         list current file in ls -dils format on standard output.

[方式1]

find . -type f -newermt "2021-08-04 18:40" ! -newermt "2021-08-04 18:55" -ls

Or

[方式2]

touch --date="2021-08-04 18:40" start

touch --date="2021-08-04 18:55" stop

find / -newer start \! -newer stop -ls

user(-uid/-usr)

-uid n

-user <uname>

group(-gid/-group)

-gid n

-group gname

filename(-name/-iname)

-name pattern          # case sensitive

-iname pattern         # case insensitive

Base of  file name (the path with the leading directories removed) matches shell pattern.

=> "-name a/b" will never match anything (use -path instead)

pattern

  • "*", "?", "[]" match a `.' at the start of the basename
  • Braces("{}") are not recognised as being special

e.g.

touch {1,12,123,.12}.txt

find . -name "???.txt"    # Output ./.12.txt ./123.txt

Notes

 * To enclose the pattern in quotes in order to protect it from expansion by the shell.

另見 -regex


Size

 

-size n[cwbkMG]

units

  • 'b'    for 512-byte blocks
  • 'c'    for bytes
  • 'k'    for Kilobytes
  • 'M'    for Megabytes
  • 'G'    for Gigabytes

# 找出大過 10M 的東西

find . -size +10M

 


Type

 

-type f | d | l | ...

 


Permission

 

-perm mode

  • u = user
  • g = group
  • o = other
  • a = all

find . -perm NNN

664         <-- permission 是 644

-664        <-- 最少有這些 bit 的意思 (This will match a file which has mode 0777)

All of the permission bits mode are set for the file.

[without regard to the presence of any extra permission bits]

/222         <-- Search for files which are writable by somebody

Any of the permission bits mode are set for the file.

        touch 600 060 006 066 660 606 666       # 7 Files

        chmod 600 600; chmod 060 060; chmod 006 006

        chmod 066 066; chmod 660 660; chmod 606 606; chmod 666 666

        find . -perm /220     # 不中 006

        find . -perm /202     # 不中 060

All three of these commands do the same thing

  • find . -perm /220
  • find . -perm /u=w,g=w    
  • find . -perm /u+w,g+w

"!"

 

find . \! -user foo -print     # 找出 other 沒有 read 的 file / folder

find . ! -perm -o=r            # 這 cmd 可能會漏了沒有 "x" 的 Folder

find . -type f ! -perm -o=r

find . -type d ! -perm -o=rx

# To find all SGID files:

find / -xdev -type f -perm +g=s -print

# To find all SUID files

find / -xdev -type f -perm +u=s -print

 


Depth

 

-maxdepth levels

-mindepth levels

 


regex

 

# File name matches regular expression pattern.

find /proc -maxdepth 1 -regex '/proc/[0-9]+'

 


path

 

-path pattern

File name matches shell pattern pattern (do not treat `/' or `.' specially)

i.e.

# 會中 "./src/misc"

find . -path "./sr*sc"

# never match anything

find bar -path /foo/bar/myfile -print

 * 在 bar 之下的 path 會是 bar/123, bar/234 之類

# Exclude top level directory (首個出現的結果: ".")

find . ! -path . -type d -mtime -90 -print

# 應用情況: 以下指令把所有 Folder copy 了, 而不是 90 日內的 Folder

find . -type d -mtime -90 -exec cp -a {} /data/apps/data/tmp \;

.
./43263
./43224
...

Note: 同效

find . -mindepth 1 -type d -mtime -90 -print

 

 


Symbolic

 

-L     Follow symbolic links

# fine link file only

find . -maxdepth 1 -type l

 


Action - prune

 

它是 ACTIONS 來, 當中了 "條件" 後就會 ignore 之後的 tree

i.e. 在當前目錄下找出 90 內更新過名叫 tmp 的頂層 Folder

find . -type d -mtime -90 -path "*/tmp*" -prune

 


Action - exec

 

find . -type f -exec file '{}' \;

remark

'{}' 與 \; 之間要有空格

 


find 與 xargs

 

find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f

解釋

find 的 -print0

# print the full file name on the stout followed by a null character

(instead of the newline character that -print uses)

xargs 的 -0

# Input items are terminated by a null character instead of by whitespace

 


A pipe "|" in linux 's find -exec command

 

# top level shell to perform the piping

# 缺點是不知每目錄內郵件數量

find . -type d -name cur -exec ls -1 "{}" \; | wc -l

# execute via sh

 * 注意: This "{}" in your first command may even lead to code injection.

 * 不建議用, 檔名有空格都已經出事.

    (literally named " & rm -rf ~ & : ".txt)

find . -type d -name cur -exec sh -c 'echo {}; ls -1 {} | wc -l' \;

 


應用

 

1) 將 mail 按年歸類

ie. 2021 年

su vmail -s /bin/bash

touch --date="2021-01-01 00:00" startref
touch --date="2022-01-01 00:00" stopref

mkdir -p .2021/cur
ls -d .2021/cur

find cur -type f -newer startref \! -newer stopref -exec ls -l '{}' .2021/cur \;
find cur -type f -newer startref \! -newer stopref -exec mv -i '{}' .2021/cur \;

 

Creative Commons license icon Creative Commons license icon