Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

4.4. 目录和文件

4.4.1. dirname

$ dirname /usr/bin/find
/usr/bin
    	

4.4.2. filename

$ basename /usr/bin/find
find
    	
排除扩展名
file=test.txt
b=${file%.*}
echo $b
	    	
$ for file in *.JPG;do mv $file ${file%.*}.jpg;done
	    	
取扩展名
file=test.txt
b=${file##*.}
echo $b
	    	

4.4.3. test - check file types and compare values

		
test -x /usr/bin/munin-cron && /usr/bin/munin-cron
		
		

4.4.4. file — determine file type

$ file mis.netkiller.cn-0.0.1.war 
mis.netkiller.cn-0.0.1.war: Zip archive data, at least v2.0 to extract

$ file dian_icon.png 
dian_icon.png: PNG image data, 8 x 24, 8-bit/color RGBA, non-interlaced

$ file sms-s3.jpg
sms-s3.jpg: JPEG image data, JFIF standard 1.01

$ file -i favicon.ico 
favicon.ico: image/x-icon; charset=binary

$ file netkiller.wmv 
netkiller.wmv: Microsoft ASF

$ file netkiller.flv
netkiller.flv: Macromedia Flash Video

$ file neo.swf
neo.swf: Macromedia Flash data (compressed), version 10

$ file cs800.css 
cs800.css: ISO-8859 text, with CRLF line terminators
		

查看mime

$ file -i sms.jpg
sms.jpg: image/jpeg; charset=binary

$ file -i call.png
call.png: image/png; charset=binary

$ file -i cs800.css
cs800.css: text/plain; charset=iso-8859-1

$ file -i neo.swf
neo.swf: application/x-shockwave-flash; charset=binary

$ file -i neo.wmv
neo.wmv: video/x-ms-asf; charset=binary

$ file -i neo.flv
neo.flv: video/x-flv; charset=binary
		

4.4.5. stat

modification time(mtime,修改时间):当该文件的“内容数据”更改时,会更新这个时间。内容数据指的是文件的内容,而不是文件的属性。
status time(ctime,状态时间):当该文件的”状态(status)”改变时,就会更新这个时间,举例,更改了权限与属性,就会更新这个时间。
access time(atime,存取时间):当“取用文件内容”时,就会更新这个读取时间。举例来使用cat去读取该文件,就会更新atime了。
		
[root@apache www]# stat index.html
  File: `index.html'
  Size: 145355          Blocks: 296        IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 15861815    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (  502/  upuser)   Gid: (  502/  upuser)
Access: 2010-10-28 11:09:52.000000000 +0800
Modify: 2010-10-28 10:23:13.000000000 +0800
Change: 2010-10-28 10:23:13.000000000 +0800
		

4.4.6. mkdir - make directories

mkdir -p /tmp/test/{aaa,bbb,ccc,ddd}

mkdir -p /tmp/test/{aaa,bbb,ccc,ddd}/{eee,fff}

mkdir -p /tmp/test/{2008,2009,2010,2011}/{01,02,03,04,05,06,07,08,09,10,11,12}/{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}
		

4.4.7. rename

批量更改扩展名

rename 's/\.png/\.PNG/' *.png

rename 's/\.mp3/\.MP3/' *.mp3
rename .mp3 .MP3 *.mp3

rename GIF gif *.GIF
		
for file in *.GIF
do
        mv $file ${file%.*}.gif
done
		
$ mkdir chapter.command.xxx.xml
$ mkdir chapter.command.bbb.xml
$ mkdir chapter.command.ccc.xml
$ mkdir chapter.command.ddd.xml

$ rename 's/command/cmd/' *.command.*.xml
		

4.4.8. touch

创建空文件,修改文件日期时间

touch [-acdmt] 文件
参数:
-a : 仅修改access time。
-c : 仅修改时间,而不建立文件。
-d : 后面可以接日期,也可以使用 --date="日期或时间"
-m : 仅修改mtime。
-t : 后面可以接时间,格式为 [YYMMDDhhmm]

# touch filename
# touch -d 20050809 filename
# touch -t 0507150202 bashrc
# touch -d "2 days ago" bashrc
# touch --date "2011-06-03" filename
		

4.4.9. truncate

truncate - shrink or extend the size of a file to the specified size

创建指定大小的文件

truncate -s 1k /tmp/test.txt
truncate -s 100m /tmp/test100.txt	
		

4.4.10. ls - list directory contents

$ ls
$ ls ~
$ ls -l
$ ls -a
$ ls -1
$ ls -F
bg7nyt.txt*  Desktop/    Firefox_wallpaper.png  Music/     public_html@  Videos/
bg7nyt.wav*  Documents/  Mail/                  nat.txt*   script/       workspace/
BOINC/       Examples@   mbox                   Pictures/  Templates/
		

{}通配符

ls {*.py,*.php,*.{sh,shell}}
		

take a look at below

alias l='ls -CF'
alias la='ls -A'
alias ll='ls -l'
alias ls='ls --color=auto'
		
full-time / time-style 定义日期时间格式

默认风格

[www@www.netkiller.cn ~]$ ls -l /var/log/message*
-rw------- 1 root root 302533 Jun 18 09:50 /var/log/messages
-rw------- 1 root root 392028 May 23 03:30 /var/log/messages-20160523
-rw------- 1 root root 334328 May 29 03:09 /var/log/messages-20160529
-rw------- 1 root root 395792 Jun  5 03:44 /var/log/messages-20160605
-rw------- 1 root root 308984 Jun 13 03:33 /var/log/messages-20160613
			

修改后

--full-time = --time-style=full-iso

[www@www.netkiller.cn ~]$ ls -l --full-time /var/log/messages*
-rw------- 1 root root 308659 2016-06-18 10:24:49.186979051 +0800 /var/log/messages
-rw------- 1 root root 392028 2016-05-23 03:30:01.869219181 +0800 /var/log/messages-20160523
-rw------- 1 root root 334328 2016-05-29 03:09:02.158442470 +0800 /var/log/messages-20160529
-rw------- 1 root root 395792 2016-06-05 03:44:02.424073354 +0800 /var/log/messages-20160605
-rw------- 1 root root 308984 2016-06-13 03:33:02.004785063 +0800 /var/log/messages-20160613

[www@www.netkiller.cn ~]$ ls -l --time-style=full-iso /var/log/messages*
-rw------- 1 root root 308659 2016-06-18 10:24:49.186979051 +0800 /var/log/messages
-rw------- 1 root root 392028 2016-05-23 03:30:01.869219181 +0800 /var/log/messages-20160523
-rw------- 1 root root 334328 2016-05-29 03:09:02.158442470 +0800 /var/log/messages-20160529
-rw------- 1 root root 395792 2016-06-05 03:44:02.424073354 +0800 /var/log/messages-20160605
-rw------- 1 root root 308984 2016-06-13 03:33:02.004785063 +0800 /var/log/messages-20160613
			

long-iso

[www@www.netkiller.cn ~]$ ls -lh --time-style long-iso /var/log/message*
-rw------- 1 root root 296K 2016-06-18 10:00 /var/log/messages
-rw------- 1 root root 383K 2016-05-23 03:30 /var/log/messages-20160523
-rw------- 1 root root 327K 2016-05-29 03:09 /var/log/messages-20160529
-rw------- 1 root root 387K 2016-06-05 03:44 /var/log/messages-20160605
-rw------- 1 root root 302K 2016-06-13 03:33 /var/log/messages-20160613			
			

通过配置 TIME_STYLE 环境变量,改变日期格式

[www@www.netkiller.cn ~]$ export TIME_STYLE=long-iso

[www@www.netkiller.cn ~]$ ls -l /var/log/message*
-rw------- 1 root root 302533 2016-06-18 09:50 /var/log/messages
-rw------- 1 root root 392028 2016-05-23 03:30 /var/log/messages-20160523
-rw------- 1 root root 334328 2016-05-29 03:09 /var/log/messages-20160529
-rw------- 1 root root 395792 2016-06-05 03:44 /var/log/messages-20160605
-rw------- 1 root root 308984 2016-06-13 03:33 /var/log/messages-20160613
			
[www@www.netkiller.cn ~]$ export TIME_STYLE=iso
[www@www.netkiller.cn ~]$ ls -l /var/log/message*
-rw------- 1 root root 302533 06-18 09:50 /var/log/messages
-rw------- 1 root root 392028 05-23 03:30 /var/log/messages-20160523
-rw------- 1 root root 334328 05-29 03:09 /var/log/messages-20160529
-rw------- 1 root root 395792 06-05 03:44 /var/log/messages-20160605
-rw------- 1 root root 308984 06-13 03:33 /var/log/messages-20160613
			

自定义格式

[www@www.netkiller.cn ~]$ ls -l --time-style="+%Y-%m-%d" /var/log/message*
-rw------- 1 root root 302533 2016-06-18 /var/log/messages
-rw------- 1 root root 392028 2016-05-23 /var/log/messages-20160523
-rw------- 1 root root 334328 2016-05-29 /var/log/messages-20160529
-rw------- 1 root root 395792 2016-06-05 /var/log/messages-20160605
-rw------- 1 root root 308984 2016-06-13 /var/log/messages-20160613

[root@www.netkiller.cn ~]# export TIME_STYLE='+%Y/%m/%d %H:%M:%S'
[root@www.netkiller.cn ~]# ls -l /var/log/messages*
-rw------- 1 root root 189352 2016/06/18 10:20:01 /var/log/messages
-rw------- 1 root root 322453 2016/05/22 03:48:02 /var/log/messages-20160522
-rw------- 1 root root 247398 2016/05/30 03:37:01 /var/log/messages-20160530
-rw------- 1 root root 174633 2016/06/05 03:14:02 /var/log/messages-20160605
-rw------- 1 root root 196728 2016/06/12 03:17:01 /var/log/messages-20160612
			

4.4.11. cp - copy files and directories

copy directories recursively
cp -r /etc/* ~/myetc
			
覆盖已存在的文件
overwrite an existing file

-f, --force 覆盖已经存在的目标文件而不给出提示。 if an existing destination file cannot be opened, remove it and try again (this option is ignored when the -n option is also used)

当使用 -f 参数时仍然会提示询问覆盖

			
cp -f file1 file2

cp: overwrite 'file2'?			
			
			

使用 alias 命令查看,可以看到 cp 命令 增加 -i 参数,使用 unalias cp 可以删除 cp 别名。

			
# alias cp
alias cp='cp -i'

# unalias cp
# alias cp
-bash: alias: cp: not found
			
			

另一种解决方案是在 cp 前增加斜杠禁止别名

			
\cp -f file1 file2			
			
			
-a, --archive same as -dR --preserve=all
# cp -a file file2
			

-a 参数可以保留原文件的日期与权限等等信息。

# ll
-rw-r--r--. 1 root root      2559 Aug 27 05:00 yum.sh

# cp -a yum.sh yum1.sh
# cp yum.sh yum2.sh

# ll yum*
-rw-r--r--. 1 root root 2559 Aug 27 05:00 yum1.sh
-rw-r--r--. 1 root root 2559 Aug 27 05:58 yum2.sh
-rw-r--r--. 1 root root 2559 Aug 27 05:00 yum.sh
			

现在可以看到 yum1.sh 与 yum.sh 日期是相同的,而没有实现-a参数的 yum2.sh 日期为当前日期。

4.4.12. rm - remove files or directories

-bash: /bin/rm: Argument list too long
ls -1 | xargs rm -f
find . -name 'spam-*' | xargs rm
find . -exec rm {} \;

ls | xargs -n 10 rm -fr # 10个为一组
			
zsh: sure you want to delete all the files in /tmp [yn]?
yes | rm -i file
			

4.4.13. df - report file system disk space usage

neo@netkiller:~$ df -lh
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              19G  3.1G   15G  17% /
none                  996M  224K  996M   1% /dev
none                 1000M     0 1000M   0% /dev/shm
none                 1000M  520K 1000M   1% /var/run
none                 1000M     0 1000M   0% /var/lock
none                 1000M     0 1000M   0% /lib/init/rw
/dev/sda6              19G   13G  4.5G  75% /home
/dev/sda10            556M  178M  351M  34% /boot
/dev/sda7              46G  4.4G   40G  10% /var
/dev/sda8             367G   60G  289G  18% /opt
/dev/sda9             6.5G  143M  6.0G   3% /tmp
		

4.4.14. du - estimate file space usage

neo@netkiller:~$ sudo du -sh /usr/local
63M     /usr/local
		

4.4.15. tac - concatenate and print files in reverse

$ tac /etc/issue
Kernel \r on an \m
CentOS release 5.4 (Final)
		

4.4.16. split - split a file into pieces

按行分割文件
-l, --lines=NUMBER put NUMBER lines per output file

每10000行产生一个新文件

# split -l 10000 book.txt myfile		
			
按尺寸分割文件
-b, --bytes=SIZE put SIZE bytes per output file

下面的例子是每10兆分割为一个新文件

split -b 10m large.bin new_file_prefix			
			

4.4.17. find - search for files in a directory hierarchy

多目录匹配

{/System,}/Library/Fonts

匹配 /System/Library/Fonts 和 /Library/Fonts 两个目录

		
find {/System,}/Library/Fonts -name \*ttf		
		
		
name

Find every file under directory /usr ending in "stat".

$ find /usr -name *stat
/usr/src/linux-headers-2.6.24-22-generic/include/config/cpu/freq/stat
/usr/bin/lnstat
/usr/bin/sar.sysstat
/usr/bin/mpstat
/usr/bin/rtstat
/usr/bin/nstat
/usr/bin/lpstat
/usr/bin/ctstat
/usr/bin/stat
/usr/bin/kpsestat
/usr/bin/pidstat
/usr/bin/iostat
/usr/bin/vmstat
/usr/lib/sysstat
/usr/share/doc/sysstat
/usr/share/gnome/help/battstat
/usr/share/omf/battstat
/usr/share/zsh/help/stat
/usr/share/zsh/4.3.4/functions/Completion/Unix/_diffstat
/usr/share/zsh/4.3.4/functions/Completion/Zsh/_stat
/usr/share/zsh/4.3.4/functions/Zftp/zfstat
		
find  \( -iname '*.jpg' -o -iname '*.png' -o -iname '*.gif'  \)

find /www/images -type f \( -iname '*.js' -o -iname '*.css' -o -iname '*.html' \) | xargs tar -czf ~/images.tgz
		

使用通配符

find . -name "*.jsp" -delete
find . -name "*.xml" -delete		
		
regex
find . -regex ".*\.\(jpg\|png\)"
		

下面regex与name作用相同

find . -regex ".*\.\(txt\|sh\)"
find . -name "*.sh" -o -name "*.txt"
		

-regex参数,使用正则表达式来匹配. 查找当前目录以及子目录中以 ".sh",并改为以".shell"结尾.

		
[neo@netkiller test]# tree a
a
├── a.py
├── a.sh
└── b
    ├── b.py
    ├── b.sh
    ├── c
    │   └── c.sh
    └── d
        └── d.sh

[neo@netkiller test]# find ./a -type f  -regex ".*\.sh$" | sed -r -n 's#(.*\.)sh$#mv & \1shell#e'
[neo@netkiller test]# tree a
a
├── a.py
├── a.shell
└── b
    ├── b.py
    ├── b.shell
    ├── c
    │   └── c.shell
    └── d
        └── d.shell
        
 // 注意 sed s->e  使用方式,官方文档是这样解释的.
This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a NUL character. This is a GNU sed extension.
		
		
user

Find every file under /home and /var/www owned by the user neo.

$ find /home -user neo
$ find /var/www -user neo
$ find . -user nobody -iname '*.php'
		
perm
find ./ -perm -7 -print | xargs chmod o-w
find . -perm -o=w
		

查找当前目录下权限为777的文件并显示到标准输出

find ./ -type f -perm 777 -print		
		
type
分别设置文件与目录的权限
find /usr/www/phpmyadmin -type d -exec chmod 755 {} \;
find /usr/www/phpmyadmin -type f -exec chmod 644 {} \;
			
-delete
# find /var/spool/clientmqueue/ -type f -delete
		

保留最近7天的问题,其他全部删除

find . -type f -mtime +7 -delete
		
			
find . -type f -name "*.xhtml" -delete
			
		
exec

替换文本

# find ./ -exec grep str1 ‘{}’ \; -exec sed -i.bak s/str1/str2/g ‘{}’ \;
		
find -exec ls -l {} \; | grep '2011-01-18'
		

查找*.html文件中aaa替换为bbb

find . -name "*.html" -type f -exec sed -i "s/aaa/bbb/" {} \;		
		

查找文件中含有openWindow字符串的文件

# find -type f -name "*.js" -exec grep -H -A2 openWindow {} \;

./javascript/commonjs.js:function openWindow(url){
./javascript/commonjs.js-	window.open(url + "?rand=" + getRandom(), 'gamebinary');
./javascript/commonjs.js-}
		
find -type f -regex ".*\.\(css\|js\)" -exec yuicompressor {} -o {} \;
find -type f -name "*.js" -exec yuicompressor --type js {} -o {} \;
find -type f -name "*.css" -exec yuicompressor --type css {} -o {} \;
		
排除目录
find /usr/local -path "/usr/local/share" -prune -o -print

find /usr/local \( -path /usr/local/bin -o -path /usr/local/sbin \) -prune -o -print

find /usr/local \(-path /usr/local/dir1 -o -path /usr/local/file1 \) -prune -o -name "temp" -print
		

查找当前目录下的php文件,排除子目录templates_c, caches

find . \( -path ./templates_c -o -path ./caches \) -prune -o -name "*.php" -print
		
-mmin n File's data was last modified n minutes ago.
# find . -mmin +5 -mmin -10
		
find /www -type f -mtime +60s
		
-ctime

查找当前目录下超过6天且是空文件并删除

find ./ -type d -empty -ctime +6 -exec rm -f {} \;	
		

查找7天前的文件并删除

find /backup/svn/day -type f -ctime +7 -exec rm -f {} \; 
find /backup/svn/day -type f -ctime +7 -delete
find /backup/svn/day -type f -ctime +7 | xargs rm -f	
		
-mtime / -mmin

查询最近3天前内修改的文件

find . -type f -mtime -3
		

3天前

find . -type f -mtime +3
		

例 4.1. backup(find + tar)

find / -type f -mtime -7 | xargs tar -rf weekly_incremental.tar
gzip weekly_incremental.tar
			

保留7天,删除7天的日志文件

COPIES=7
find /var/log -type f -mtime +$COPIES -delete
		
--newer
tar --newer="2011-07-04" -zcvf backup.tar.gz /var/www/
tar cvzf foo.tgz /bak -N "2004-03-03 16:49:17"
		
-print / -printf
[root@scientific ~]# find / -maxdepth 1 -name '[!.]*' -printf 'Name: %16f Size: %6s\n'
Name:                / Size:   4096
Name:             misc Size:      0
Name:            media Size:   4096
Name:             home Size:   4096
Name:              dev Size:   3840
Name:              net Size:      0
Name:             proc Size:      0
Name:             sbin Size:  12288
Name:             root Size:   4096
Name:              lib Size:   4096
Name:           cgroup Size:   4096
Name:              srv Size:   4096
Name:              mnt Size:   4096
Name:              etc Size:  12288
Name:              usr Size:   4096
Name:            lib64 Size:  12288
Name:             boot Size:   1024
Name:              var Size:   4096
Name:          selinux Size:      0
Name:              opt Size:   4096
Name:              tmp Size:   4096
Name:       lost+found Size:  16384
Name:              sys Size:      0
Name:              bin Size:   4096

# find /etc/ -type f -printf "%CY-%Cm-%Cd %Cr %8s %f\n"
		
-size

查找0字节文件

find /www -type f -size 0
		

查找根目录下大于1G的文件

find /  -type f -size +1000M		
		
-path

搜索当前目录下除了keys目录下所以子目录中的文件

find ./ -path "./keys" -prune -o -type f -print 		
		

find排除多个目录

find ./ \( -path ./conf -o -path ./logs \) -prune -o -print

find /data/ \( -path /data/data_backup -o -path /data/mysql \) -prune -o -name "core.*" -type f 
/data/mysql
/data/data_backup		
		

ps 要么都是绝对路径 要么都是相对路径 /data/ 必须有"/" path 后面的路径必须没有"/"

包含 */target/* 目录

		
[gitlab-runner@localhost cloud.netkiller.cn]$ find . -type f -name "*.jar" -path "*/target/*"
		
		

排除 lib 目录

		
[gitlab-runner@localhost cloud.netkiller.cn]$ find . -type f -name "*.jar" ! -path "lib"		
		
		

		
[gitlab-runner@localhost cloud.netkiller.cn]$ find . \( ! -path "*/zito-common/*" -a ! -path "./lib/*" \) -type f -name "*.jar"
		
		
目录深度控制
		
neo@MacBook-Pro ~/workspace/Linux % find */images -type d -d 0 -exec echo {} \;
Cryptography/images
Monitoring/images
OpenLDAP/images
Project/images
Web/images
		
		
		
find */images -type d -d 0 -exec rsync -au {}/* $(PUBLIC_HTML)/linux/images \; 		
		
		
-maxdepth

-maxdepth和-mindepth,最大深度,最小深度搜索,搜索当前目录下最大深度为1的所以文件

find . -maxdepth 1 -type f 		
		
xargs
find /etc -type f|xargs md5sum
		

sha1sum

find /etc -type f|xargs sha1sum
		
find ./ -name "*html" | xargs -n 1 sed -i -e 's/aaa/bbb/g'
		
find /tmp -name core -type f -print | xargs /bin/rm -f
find . -type f -exec file '{}' \;
		

find后执行xargs提示xargs: argument line too long解决方法:

find . -type f -name "*.log" -print0 | xargs -0 rm -f		
		

-i 参数可以使用 {}

		
[gitlab-runner@localhost cloud.sfzito.com]$ find . \( ! -path "*/zito-common/*" -a ! -path "./lib/*" -a ! -path "./dist/*" \) -type f -name "*.jar" | xargs -i cp {} dist/