Linux 文件命令
文件与目录
witch
没有这个 witch (巫婆) 命令啦,老是将 which (哪一个) 打成 witch。
那卡住了怎么办? ls 应该记得起来吧,另再记两个目录 /bin
、/usr/bin
。
$ls \bin\w*
ls: cannot access 'binw*': No such file or directory
/
)。$ls /bin/w*
/bin/wdctl /bin/which /bin/whiptail
好!看到了 which
是在 /bin/which
。
/bin/which
去找 which
/bin/which which
/usr/bin/which
疑?用 /bin/which
去找 which
结果是 /usr/bin/which
。
path
。$echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
原来运行 which
时是按 path
搜索,先找 /usr/bin
再找 /bin
,缺省行为是找到后就不再继续运行。
which
有没有可以找出全部的 path
的参数?$which -h
Illegal option -h
Usage: /usr/bin/which [-a] args
$which --help Illegal option -h Usage: /usr/bin/which [-a] args
-a
吧,一个说明都要这么省。which -a which
/usr/bin/which /bin/which
/usr/bin/which
$ls /usr/bin/which -l
lrwxrwxrwx 1 root root 10 2019-10-21 13:23 /usr/bin/which -> /bin/which
/usr/bin/which
是链接至 /bin/which
,不过这里有点疑问,linux 已经把 /bin
纳入 PATH 了,
不知道为什么还要在 /usr/bin
做链接,也许是要让学习 linux 困难一点?
journalctl
这个命令这么长,老是忘记,来一个 ls
吧!$ls /bin/j*
/bin/journalctl
journalctl
又有链接? 幸好没有,要不然全乱了。$which -a journalctl
/bin/journalctl
which 太方便了,好吧!建一个 Windows which。
@setlocal @set P2=.;%PATH% @for %%e in (%PATHEXT%) do @for %%i in (%~n1%%e) do @if NOT "%%~$P2:i"=="" echo %%~$P2:i
不过也不需要啦,Windows 用 where
即可。
ls 查看目录与文件
ls [选项] [文件或目录]
|
以每行列出详细数据 |
|
以高可读性显示文件容量大小 (如 1K 2M 3G)。 |
|
显示所有文件,含隐藏档。 |
|
显示所有文件,但不包括 |
|
列出该目录而不是目录内的文件。 |
|
递归,含目录内的所有文件。 |
|
排序时倒序。 |
|
依时间排序。 |
|
依文件容量大小排序。 |
|
加入指示字符,如将目录后置 |
|
列出实际保存于文件系统中的索引码,可参阅后文的硬链接。 |
export TIME_STYLE=long-iso
for F in $(ls *.txt); do \
echo $F; \
done
cp 拷贝
cp [参数] 来源 目的
|
递归,含目录内的所有文件。 |
|
拷贝文件 (或目录) 的拥有者及群组 (ownership),文件权限 (mode) 及时间 (timestamps),拥有者及群组仅限超级用户 (即为 root) 才会拷贝。 |
|
保留文件链接 (跟 |
|
保留文件链接。 |
|
连同特殊属性 (拥有者、群组、文件权限、时间、链接、xattr) 一并拷贝,拥有者及群组仅限超级用户 (即为 root) 才会正确。 |
|
跟 |
|
拷贝链接档的实际文件。 |
|
拷贝软链接 (never follow symbolic links in SOURCE)。 |
|
保留来源目录结构。 |
|
强制运行,在无法写入目的文件时,尝试删除目的文件后,再次重新拷贝 (同时具有 |
|
先删除目的文件,再运行拷贝。 |
|
不要覆盖现有的文件。 |
|
在覆盖文件之前,先询问。 |
|
更新,当来源比「目的」新或「目的」缺少才会拷贝。 |
|
将文件拷贝成硬链接。 |
|
将文件拷贝成软链接。 |
|
指定备份档的结尾名称,未指定为 |
|
备份目的文件 (若目的文件已存在,将目的文件名增加结尾名称,如果结尾名称的文件已存在,先删除再改名)。 |
- 基本操作
-
文件拷贝
cp 来源文件 目的文件
将文件拷贝到其他目录,可指定目的目录 (保留源文件案名称)cp 来源文件 已存在的目的目录/
多档拷贝cp 来源档1 来源档2 来源档3 已存在的目的目录/
拷贝目录cp -r /path/folder 添加的目的目录
当目的目录不存在时则拷贝至该目的目录。
但如果目的目录存在则拷贝至该目录内,递归拷贝目录内容,需在来源目录后增加一个*
(通配字符)。递归拷贝目录内容cp -r /path/folder/* 已存在的目的目录 (1)
1 若 /path/folder/*
改为/path/folder/
,则拷贝至已存在的目的目录/folder
。 - cp 缺省行为
-
-
拥有者及群组 (ownership) 权限为操作帐户。
-
拷贝文件权限 (mode)
-
将硬链接转成一般文件。
-
拷贝软链接。
-
覆盖文件且不会询问。
-
不会删除目的目录的多余文件。
-
- 不要覆盖现有的文件
-
不要覆盖现有的文件
-n
,文件已存在,并不会运行拷贝。cp -n source.txt dest.txt
或者在覆盖文件之前,先询问-i
。$cp -i source.txt dest.txt cp: overwrite 'dest.txt'?
更新文件 (-u
),来源文件的修改时间比目的文件还新,或者目的文件缺少,则更新文件cp -u source.txt dest.txt
以-iur
来得知目录内那些文件需要更新$cp -iur source/* dest cp: overwrite 'dest/source.txt'?
- 强制覆盖文件
-
如果目的文件文件无法写入(如权限为唯读),则无法运行拷贝。
$cp soruce.txt dest.txt cp: cannot create regular file 'dest.txt': Permission denied
以-f
强制运行cp -f soruce.txt dest.txt
以--remove-destination
先删除目的文件,再运行拷贝。cp --remove-destination soruce.txt dest.txt
- 备份目的文件
-
覆盖目的文件时,若需备份可采用
-b
备份目的文件。备份目的文件-b
cp -b source.txt dest.txt
缺省会将目的文件的结尾名称加上
~
,例如dest.txt
会备份至 (改名为)dest.txt~
,如果dest.txt~
已存在,则先删除dest.txt~
再将dest.txt
改名。指定备份结尾文件名以-S
来设置。指定备份目的文件-S .bak
cp -b -S .bak source.txt dest.txt
dest.txt
则备份至dest.txt.bak
,如果dest.txt.bak
已存在,则先删除dest.txt.bak
再将dest.txt
改名。 - 拷贝链接文件
-
拷贝文件时,拷贝连接文件的目标文件,可采用
-L
拷贝链接档的目标文件,拷贝后为一般文件。
如link.txt
是指向source.txt
的链接档,dest.txt
实际上是拷贝source.txt
。-L
拷贝链接档的目标文件。cp -L link.txt dest.txt
在拷贝软链接文件时,将软链接直接拷贝,可采用
-P
拷贝软链接,如soft-link
是一个软链接,拷贝后的dest.txt
亦为软链接文件。这里为什么要强调是软链接?
因为硬链接会拷贝成一般文件。-P
拷贝软链接cp -P soft-link.txt dest.txt
保留文件链接
-d
的情况比较复杂,当硬链接的目标文件在相同的目录一起被拷贝时,则以硬链接拷贝,其他情况则转成一般文件。
如在source
目录内,文件source.txt
的硬链接为link.txt
,在目录中创建硬链接other-link.txt
链接至other/source.txt
列出测试目录的内容$ls other source -liU other: total 4 2935287 -rw-rw-r-- 2 ubuntu ubuntu 4 1970-01-01 08:00 source.txt source: total 12 2935287 -rw-rw-r-- 2 ubuntu ubuntu 4 1970-01-01 08:00 other-link.txt 2935285 -rw-rw-r-- 2 ubuntu ubuntu 4 1970-01-01 08:00 source.txt 2935285 -rw-rw-r-- 2 ubuntu ubuntu 4 1970-01-01 08:00 link.txt
以保留文件链接-d
,将目录source
拷贝至目录dest
。$cp -rd source dest $ls dest/source.txt dest/link.txt dest/other-link.txt -liU 2935289 -rw-rw-r-- 2 ubuntu ubuntu 4 2023-03-12 13:43 dest/source.txt (1) 2935289 -rw-rw-r-- 2 ubuntu ubuntu 4 2023-03-12 13:43 dest/link.txt (1) 2935290 -rw-rw-r-- 1 ubuntu ubuntu 4 2023-03-12 13:43 dest/other-link.txt (2)
1 硬链接的源文件一起被拷贝,则会以硬链接拷贝。 2 不在相同的目录则会转成一般文件。 以参数-d
拷贝dest/link.txt
至dest/dest.txt
,dest/dest.txt
视为一般文件。$cp -d dest/link.txt dest/dest.txt $ls dest/dest.txt -li 2935291 -rw-rw-r-- 1 ubuntu ubuntu 4 2023-03-12 14:42 dest/dest.txt
- 以软、硬链接拷贝文件
-
以参数
-s
将文件拷贝成软链接,等同于ln -s
命令创建链接,link.txt
是一个指向source.txt
的链接档。将文件拷贝成软链接-s
。cp -s source.txt link.txt
以参数
-l
将文件拷贝成硬链接,等同于ln
命令创建链接,link.txt
是source.txt
的分身 (inode 相同)。将文件拷贝成硬链接-l
。cp -l source.txt link.txt
以cp
创建链接比ln
的好处是可一次创建目录下多个链接。cp -sr $PWD/source soft-dest cp -lr source hard-dest
- 拷贝拥有者及群组、文件权限及时间
-
拷贝拥有者、群组、文件权限及时间
-p
或-a
,以超级用户 (即为 root) 运作时,拥有者及群组权限才会拷贝。拷贝文件权限及时间-p
sudo cp -p source.txt dest.txt
拷贝文件权限及时间及保留链接-a
sudo cp -a source.txt dest.txt
- 保留来源目录结构
-
--parents
保留来源目录结构。mkdir -p path/to touch path/to/source.txt mkdir dir-parents cp --parents path/to/source.txt dir-parents/
$tree path (1) path └── to └── source.txt $tree dir-parents dir-parents └── path └── to └── source.txt
1 若没有 tree
命令,以sudo apt install tree
安装。
scp 安全拷贝远程目录与文件
scp 是 secure copy 的缩写,基于 ssh 安全通信拷贝远程的文件 (目录)。
scp
命令的语法跟 cp
类似,scp
可在主机之间拷贝文件,其语法为:scp [[来源帐号@]来源主机:]来源文件或目录 [[目的帐号@]目的主机:]目的文件或目录
省略帐号与主机,表示本机的文件,只省略帐号表示本地端的用户帐号跟远程帐号一样。
|
递归,含目录内的所有文件。 |
|
保留文件时间 |
|
压缩之后再发送 |
|
限制网络带宽,单位为 Kbit/s。 |
|
拷贝源文件案的修改时间、访问时间和文件权限 (mode)。 |
- 基本操作
-
以
ubuntu
帐号登录192.168.1.1
主机,将主机上的/path/file
拷贝到本地端的/path/file
。
本地端的用户帐号跟远程的用户帐号一样时,可省略用户帐号。从远程文件拷贝到本地端scp ubuntu@192.168.1.1:/path/file /path/file
在运行命令时,会以 SSH 登录远程的主机,需输入ubuntu@192.168.1.1
的密码 (公开密钥连接 SSH 服务器除外):ubuntu@192.168.1.1's password:
从远程文件拷贝到本地端,省略帐号scp 192.168.1.1:/path/file /path/file
拷贝方向相反也类似。
由本地端文件拷贝到远程scp /path/file 192.168.1.1:/path/file
从远程目录拷贝到本地端scp -r 192.168.1.1:/path/folder 添加的目的目录
当目的目录不存在时则拷贝至该目的目录。
但如果目的目录存在则拷贝至该目录内,递归拷贝目录内容,需在来源目录后增加一个 * (通配字符)。递归拷贝目录内容scp -r 192.168.1.1:/path/folder/* 已存在的目的目录 (1)
1 若把 /path/folder/*
改成/path/folder/
,则拷贝至已存在的目的目录/folder
。
-p
。scp -p 192.168.1.1:/path/file /path/file
scp -l 100 192.168.1.1:/path/file /path/file (1)
1 | -l 跟数字之间,可不需要空白字符。 |
-C
。scp -C 192.168.1.1:/path/file /path/file
scp -P 222 192.168.1.1:/path/file /path/file
rm (删除)、mv (移动或改名)
- rm
-
rm 移除的文件或目录
rm 选项 -r, -R
递归,含目录内的所有文件。
-f
强制删除不会询问。
- mv
-
mv 移动(或改名)来源 目的
mv 是 move 的缩写,除了移动的功能外也可以重命名。将「来源」移动至「目的」,如果「目的」为存在的文件则会被覆盖。
ln 文件链接
通过链接文件,不同的文件名可以指向同一个文件。链接类型分为硬链接 (hard link) 和符号链接 (symbolic link) 两种,符号链接也称软链接 (soft link),缺省的链接类型是硬链接。
- 软链接
-
软链接为一个独立的文件或目录,类似于 Windows 操作系统中的快捷方式方式。
软链接本身有文件属性及权限。
软链接可以跨文件系统。
软链接可以对目录进行链接。
删除软链接并不影响目标文件,若目标文件被删除,则相关软链接被称为已断开的悬挂链接 (dangling link),当重新创建目标时则悬挂链接可恢复为正常。
创建不存在目标的软链接 (跟悬挂链接相似),不会提示错误 (注:ls
会将指向显示成红色)。
绝对路径所创建的链接档,在搬移软链接档时目标位置会相同,而以相对路径创建的链接档,其目标位置则会变动。
- 硬链接
-
只能处理文件链接。
创建硬链接,事实上是在文件系统中创建分身,在文件系统中不同文件的索引码 inode 相同。
删除其中一个分身,只要有一个分身存在,那么文件实体就不会被删除。
删除所有分身,文件实体则被删除。
ln [参数] 目标(TARGET) 链接名称(LINK_NAME)
本文中将「链接名称」指向的文件 (或目录) 称为「目标」。
「链接名称」为「软链接」或「硬链接」。
|
创建软链接。 |
|
创建相对路径的软链接。 |
|
创建成硬链接 (默认值,不需指定本参数)。 |
|
强制运行 (链接存在时先删除文件)。 |
|
交互模式,链接存在时提示是否取代。 |
|
指定备份文件名的结尾名称,未指定为 |
|
备份链接文件 (若链接文件已存在,将链接文件名增加结尾名称,如果结尾名称的文件已存在,先删除再改名)。 |
|
显示详细的处理过程 |
- 创建软链接
-
以参数
-s
,将source.txt
创建softlink.txt
软链接档。创建软链接-s
ln -s source.txt softlink.txt
链接至不同目录,创建的「目标」是相对于「链接名称」的路𠇹。
在source
目录中创建一个source.txt
文件,并创建一个dest
目录mkdir source echo 123 > source/source.txt mkdir dest
在dest
目录中,创建相对路径目标../source/source.txt
的软链接RelLink1.txt
cd dest ln -s ../source/source.txt RelLink1.txt
在目录中,创建的目标很直觉会采用正确的相对路径。
但如果在目录外往往会出错。创建错误的软链接 ErrorLink.txtcd .. ln -s source/source.txt dest/ErrorLink.txt
正确的「目标」是「链接名称」位置的相对路𠇹 (当做目前路径是「链接名称」的目录内)。ln -s ../source/source.txt dest/RelLink2.txt
或者以-r
创建相对路径的软链接。ln -sr source/source.txt dest/RelLink3.txt
创建绝对路径的AbsLink.txt
ln -s $PWD/source/source.txt dest/AbsLink.txt
显示dest
目录内置立的软链接文件。$ls dest -li total 0 2906099 lrwxrwxrwx 1 ubuntu ubuntu 35 2023-03-12 20:32 AbsLink.txt -> /home/ubuntu/demo/source/source.txt 2893916 lrwxrwxrwx 1 ubuntu ubuntu 17 2023-03-12 20:31 ErrorLink.txt -> source/source.txt 2893902 lrwxrwxrwx 1 ubuntu ubuntu 20 2023-03-12 20:31 RelLink1.txt -> ../source/source.txt 2894388 lrwxrwxrwx 1 ubuntu ubuntu 20 2023-03-12 20:31 RelLink2.txt -> ../source/source.txt 2894401 lrwxrwxrwx 1 ubuntu ubuntu 20 2023-03-12 20:32 RelLink3.txt -> ../source/source.txt
- 创建硬链接
-
创建目标为
source/source.txt
的dest/HardLink.txt
硬链接ln -P source/source.txt dest/HardLink.txt (1)
1 -P
为默认值,可不需要该参数。硬链接是使用相同的 inode,没有相对路径的问题。
显示source/source.txt
dest/HardLink.txt
的 inode$ls source/source.txt dest/HardLink.txt -lU --inode 2935285 -rw-rw-r-- 2 ubuntu ubuntu 4 2023-03-12 20:05 source/source.txt 2935285 -rw-rw-r-- 2 ubuntu ubuntu 4 2023-03-12 20:05 dest/HardLink.txt
两个不同文件,实际保存于文件系统中的索引码 (inode) 为 2935285,在文件权限后面的数字 2 表示该文件有 2 个硬链接。
删除硬连接 (应该说删除其中一个分身)$rm source/source.txt (1) $ls dest/HardLink.txt -lU --inode 2935285 -rw-rw-r-- 1 ubuntu ubuntu 4 2023-03-12 21:05 dest/HardLink.txt
1 或者以 unlink
删除连接,运行unlink source/source.txt
。删除
source/source.txt
后,前面范例的软连接已变成了悬挂链接 (dangling link)。
删除 (以rm
或unlink
)dest/HardLink.txt
后,由于文件实体没有分身,则为实际删除该文件。重建source/source
,回复原始状态。$ln dest/HardLink.txt source/source.txt $ls source/source.txt dest/HardLink.txt -lU --inode 2935285 -rw-rw-r-- 2 ubuntu ubuntu 4 2023-03-12 21:05 source/source.txt 2935285 -rw-rw-r-- 2 ubuntu ubuntu 4 2023-03-12 21:05 dest/HardLink.txt
find 找出合乎模式的文件
搜索目录之下合乎条件的文件或目录。
find [path…] [expression]
,expression 包含了林林总总的各式参数,全部混在一起。
find --help find ... [path...] [expression] expression may consist of: operators, options, tests, and actions operators ... EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2 normal options (在其他参数之前先指定 options): -depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf tests ... -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print
find
的参数有不少,可用 man find
取得详细说明。
- tests (测试参数)
-
- 名称符合
-
-name PATTERN: 文件名称符合 PATTERN,-iname 不区分大小写。
-path PATTERN: 目录名称符合 PATTERN,-ipath 不区分大小写。
目录名称包含了/
(斜线),如-ipath '*/some-path/*'
表示找出目录名称some-path
的文件,而-ipath '*/some*/*'
则找出目录名称前置some
。文件、目录名称符合 PATTERN 的外框需加单引号 ( '
) 或双引号 ("
)。否则;要转译正规表示法的特殊字符如'*.txt'
要转译成\*\.txt
。 - 文件类型符合
-
-type [bcdpflsD]: 类型参数 f 文件,l 链接档,d 目录… 。
- 文件时间符合
-
-amin 读取分钟,-atime 读取天数,-cmin 修改分钟,-ctime 修改天数
-ctime n: 文件在 n 天前修改过。
-ctime +1: +n 大于 n,所以是 2 天前修改过。
-ctime -n: 「减」表示跟目前的时间比较,在最近的 n 天内修改过的文件。 - 文件大小符合
-
-size +10M -size -20M,大于 10M 小于 20M 文件。单位:k Kilobytes,M Megabytes,G Gigabytes。
测试参数可不少直接查阅
find --help
,像找出拥有者 -user,拥有群组 -group,文件权限 -perm。找出目前路径及子路径内的 .txt 文件find . -iname '*.txt' (1)
1 目前路径可以不输入 .
。
- operators (表达式)
-
-a
、-and
-
AND (及) 逻辑,可不需要该表达式,
expr1 -a expr2
跟expr1 expr2
相同找出最近一分钟修改的 .txtfind -iname '*.txt' -a -cmin -1 find -iname '*.txt' -cmin -1
-o
、-or
-
OR (或) 逻辑
找出 .txt 或 .doc 文件: find -iname '*.txt' -o -iname '*.doc' 找出 .txt 或 .doc 文件,以长格式显示: find -iname '*.txt' -ls -o -iname '*.doc' -ls
当表达式同时有 AND、NOT、OR 时,AND、NOT 先判断之后再判断 OR。
如果 OR 两边有相同条件,两边都要加入;另外 actions 也一样两边都要加入。 !
、-not
-
NOT (否定) 逻辑
找出不为 .txt 的文件: find ! -name '*.txt' 找出拥有者不为 www-data 的文件: find ! -user 'www-data' 找出文件权限不为 775 或目录权限不为 775: find -type f -not -perm 775 -o -type d -not -perm 775 find -type f -not -perm 775 -ls -o -type d -not -perm 775 -ls
- actions (动作)
-
find -iname '.log' -ctime 7 -delete (1) find -iname '.log' -ctime -7 -ls (2)
1 删除 7 天前 .log 文件 2 以长格式列出 7 天内的 .log 文件 -exec 运行命令语法格式-
-exec 命令 {} \;
-
-exec 命令 {} +
先 (前置) 输出文件名称,再运行命令。
其中的字符串
{}
会替换成文件名称。找出 7 天内有 error 记录的 .log 文件find -iname '.log' -ctime -7 -exec grep error {} \; find -iname '.log' -ctime -7 -exec grep error {} +
-
- options (选项)
-
-maxdepth LEVELS,最大阶层。
-mindepth LEVELS,最小阶层。
注:options
需要在其他参数之前先指定。找出目前路径的 .txt 文件find . -maxdepth 1 -iname '*.txt'
rsync 远程同步文件与目录
rsync 主要用于同步 (镜像) 文件与目录,传输时比对内容仅拷贝差异文件,可减少数据传输量。
可保留文件的拥有者、群组与权限设置,删除多余的目的文件或目录。
rsync
apt install rsync
rsync [[来源帐号@]来源主机:]来源文件或目录 [[目的帐号@]目的主机:]目的文件或目录
省略帐号与主机,表示本机的文件,只省略帐号表示本地端的用户帐号跟远程帐号一样。
|
备份模式;递归备份所有子目录下的目录与文件,保留链接档、文件的拥有者及群组 (ownership)、文件权限 (mode) 以及时间戳记,跟 |
|
递归,含目录内的所有文件。 |
|
保留软链接。 |
|
保留文件权限 (mode)。 |
|
保持时间戳记。 |
|
保留拥有群组 (仅限超级用户,即为 root)。 |
|
保留拥有者 (仅限超级用户,即为 root)。 |
|
same as --devices --specials |
|
preserve device files (仅限超级用户,即为 root)。 |
|
preserve special files. |
参数 |
|
|
保留硬链接。 |
|
详细模式输出。 |
|
以可读性较高的方式来显示 (需配合 -v)。 |
|
不拷贝空目录。 |
|
传输过程中压缩文件。 |
|
测试运行。 |
|
删除多余的目的文件或目录。 |
|
设置文件或目录权限,如 |
|
设置拥有者及群组,如 |
|
传输时以单行显总体进度 ( |
|
显示每个文件的变动摘要。 |
|
设置远程登录指令。 |
|
限制网络带宽,RATE 可指定如 1.5m,未指定单位时如 100,则为 100K。 |
- 基本操作
-
同步文件,将文件
file
同步至dest/file
,会自动创建dest
目录。rsync -a /path/to/file dest/
同步目录,将目录d1
同步至d2/d1
,会自动创建d2
目录。rsync -a /path/to/d1 d2
若需将目录
d1
同步至目录d2
,同步目录内容需在来源目录后增加/
(斜线) 或是/*
(斜线及通配字符)。
当需要目录拷贝 (同步) 至目录时,可采用rsync
并在来源目录增加/
,不管目的目录是否存在,只会拷贝至目的目录。同步来源目录内容,将目录d1
同步至目录d2
,会自动创建d2
目录。rsync -a /path/to/d1/ d2 rsync -a /path/to/d1/* d2
以
ubuntu
帐号登录192.168.1.1
主机,将主机上的/path/folder
拷贝到本地端的dest
。
本地端的用户帐号跟远程的用户帐号一样时,可省略用户帐号。
可增加-z
参数,将数据压缩后再传输,减少网络传输的数据量。从远程目录同步到本地端rsync -az ubuntu@192.168.1.1:/path/folder/ dest
在运行命令时,会以 SSH 登录远程的主机,需输入ubuntu@192.168.1.1
的密码 (公开密钥连接 SSH 服务器除外):ubuntu@192.168.1.1's password:
- 同步拥有者及群组、文件权限
-
-a
已经具备了该功能,以超级用户 (即为 root) 运行rsync
时则能同步。同步本地目录文件用户权限sudo rsync -a /path/to/d1/ d2
以ubuntu
同步远程目录rsync -az /path/to/folder/ ubuntu@192.168.1.1:/path/to/folder
同步远程帐户为ubuntu
,若目的已存在而拥有者及群组不为ubuntu
时则会引发错误,如下rsync: failed to set permissions rsync: failed to modify permissions rsync: failed to set times on
远程帐户为root
,远程目的文件或目录的拥有者会同步。rsync -az /path/to/folder/ root@192.168.1.1:/path/to/folder
同步时指定目的权限为775
,拥有者及群组为www-data:www-data
。rsync -az --chmod=775 --chown=www-data:www-data /path/to/folder/ root@192.168.1.1:/path/to/folder
当本地的文件权限超出了登录帐户权限,而以sudo
运行时,也表示远程帐户也需要以root
帐户登录,那么可不需要「目的帐号」。sudo rsync -az /path/to/folder/ 192.168.1.1:/path/to/folder
- 显示文件变动摘要 (
--itemize-change
、-i
) -
$rsync --itemize-change -a /path/to/d1 d2 .d..tp..... ./ >f+++++++++ f1.txt >f..tp..... fh1.txt >f..tp..... fh2.txt cL+++++++++ fs1.txt -> f1.txt cL+++++++++ fs2.txt -> ../d2/f2.txt >f..t...... r1.txt
文件项目之前会多出 11 个字符,分别为
YXcstpoguax
。
意义如下:Y 异动类型 <
文件发送至远程
>
本地端接收文件
c
代表本地端变动(如创建目录、软链接)
h
代表本地端创建硬链接(hard link)
.
代表没有变动(但可能有变动其他属性)
*
代表其余字段有包含消息(例如 deleting)
X 文件型态 f
一般文件
d
目录
L
软链接档
D
设备档(device)
S
特殊文件(如 sockets 或 fifo)。
cstpoguax 说明 c
内容变更。
s
大小变更。
t
时间戳记变更。
o
拥有者变更。
p
文件权限 (mode) 变更。
g
群组变更。
u
保留字段。
a
ACL 变更。
x
扩充属性(extended attribute)变更。
其他值
.
无变更
+
添加文件或目录
- YXcstpoguax 示例
-
.d..t......
-
.
项目没有变动(尽管它变更了其他属性)
d
目录类型
t
时间变更 >f.st......
-
>
接收文件
f
一般文件
s
大小变更
t
时间变更 cd+++++++++
-
c
创建目录
d
目录类型
+++++++++
添加目录 >f+++++++++
-
>
接收文件
f
一般文件
+++++++++
添加文件 cL+++++++++
-
c
创建软链接档
L
软链接档
+++++++++
添加软链接档 hf..t......
-
h
创建硬链接
f
一般文件
t
时间变更
可以同时测试运行(--dry-run
、-n
),事先得知同步的情况$rsync --dry-run -ai /path/to/d1 d2 created directory d2 cd+++++++++ ./ >f+++++++++ f1.txt sent 236 bytes received 63 bytes 598.00 bytes/sec total size is 30 speedup is 0.10 (DRY RUN)
- 设置远程登录指令 (
-e
) -
如
192.168.1.1
主机的 SSH 服务连接端口为222
,以选项-e
设置远程登录指令rsync -az -e 'ssh -p 222' ubuntu@192.168.1.1:/path/folder/ dest
远程登录的缺省指令为
ssh
,参考ssh
命令加入选项-p
,将指令变更为ssh -p 222
以连接端口222
登录 SSH。 - 同步扩展名及阶层
-
同步多个扩展名,原始目录下 (第一层) 的文件,子目录并不会同步
rsync \ --include="*.svg" \ (1) --include="*.png" \ --include="*.jpg" \ --include="*.jpeg" \ --exclude='*' \ (2) $srcPath $destPath
1 指定合乎的扩展名。 2 最后条件请按范例。 拷贝原始目录 (所有) 第 2 层的扩展名rsync \ --include='/*/' \ (1) --exclude='/*' \ (2) --include="*.svg" \ --include="*.png" \ --include="*.jpg" \ --include="*.jpeg" \ --exclude='*' \ $srcPath $destPath
1 包含 1 ~ 2 层 ( 第 1 层是指原始目录下的文件,第 2 层为原始目录的子目录 )。 2 排除第 1 层 (先包含阶层再排除)。 包含阶层说明rsync \ --include='*/' \ (1) rsync \ --include='/*/' \ (2) --include='/*/*/' \ (3) --include='/*/*/*/' \ (4)
1 包含所有阶层 2 包含 1 ~ 2 层。 3 包含第 3 层 (必须先包含 1 ~2 层,才有作用)。 4 包含第 4 层 (必须先包含 1 ~2 层及第 3 层,才有作用)。 排除阶层rsync \ --include='*/' \ (1) --exclude='/*' \ (2) --exclude='/*/*' \ (3) --exclude='/*/*/*' \ (4)
1 先包含所有阶层再排除 2 排除第 1 层 (个别指定) 3 排除第 2 层 (个别指定,不需要先排除第 1 层) 4 排除第 3 层 (个别指定,不需要先排除第 1 或 2 层)
diff 列出文件差异
列出两个文件或目录的差异。
diff [参数] ... 文件或目录
|
显示差异的文件,不显示差异内容,可用于比对两个目录的文件。 |
|
递归,含目录内的所有文件。 |
|
以「上下文输出格式」显示源文件及新文件修改的情况,同时列出未变更的行数 (缺省为 3)。 |
|
以「统一格式」输出源文件修改情况,同时列出未变更的行数 (缺省为 3)。 |
|
以 RCS 格式显示 (以新文件的角度列出修改情况)。 |
|
忽略大小写。 |
|
不检查空白字符。 |
|
忽略所有空白字符,跟 |
|
忽略空行。 |
-q
diff -q folder1/ folder2/
Only in folder1: f1.txt Only in folder2: f2.txt Files folder1/f3.txt and folder2/f3.txt differ
-r
选项diff -qr folder1/ folder2/
cat > org.txt << EOF
line1-org
line2-same
del1
line3-org
del2
line4-same
del3
del4
line5-same
EOF
cat > new.txt << EOF
line1-mod
line2-same
line3-mod
line4-same
line5-same
line6-append
line7-append
EOF
diff org.txt new.txt
1c1
< line1-org
---
> line1-mod
3,5c3
< del1
< line3-org
< del2
---
> line3-mod
7,8d4
< del3
< del4
9a6,7
> line6-append
> line7-append
1c1 (1) < line1-org (2) --- > line1-mod (2)
1 | 1c1 表示 (源文件的) 第 1 行换成了 (新文件的) 第 1 行。 |
2 | < 源文件内容,> 新档内容。 |
3,5c3 (1) < del1 < line3-org < del2 --- > line3-mod
1 | 3,5c3 (源文件的) 3 至 5 行换成了 (新文件的) 第 3 行。 , 表示某行至某行,如 3,5c3,3 跟本例一样,当然开发者不会这样写;会合并相同行数。 |
7,8d4 (1) < del3 < del4
1 | 7,8d4 (源文件的) 第 7 至 8 行删除成 (新文件的) 第 4 行。 |
9a6,7 (1) > line6-append > line7-append
1 | 9a6,7 (源文件的) 第 9 行添加至 (新文件的) 6 至 7 行。 |
-u
(Unified context) 以「统一格式」输出源文件修改情况diff -u org.txt new.txt
--- org.txt 2020-10-18 14:49:06.997670700 +0800 +++ new.txt 2020-10-18 14:49:07.935176100 +0800 @@ -1,9 +1,7 @@(1) -line1-org +line1-mod line2-same -del1(2) -line3-org -del2 +line3-mod line4-same -del3 -del4 line5-same +line6-append +line7-append
1 | 提供给 patch 的数据,当未变更的行数设成 0 时 (-u0 ),可以发现还是存在 @@ 这些行,该行数据并非是「未变更」。 |
2 | 采用 -u 的表现只有 + - 及 空白 没有仿真两可的修改情况,del1 (文件内容) 为删除。 |
+
-
(不输出其他) 采用自订输出diff org.txt new.txt \
--old-line-format=$'-%l\n' \
--new-line-format=$'+%l\n' \
--unchanged-line-format=''
-c
(Copied context) 以「上下文输出格式」显示源文件及新文件修改的情况diff -c org.txt new.txt
*** 1,9 **** ! line1-org line2-same ! del1 (1) ! line3-org ! del2 line4-same - del3 - del4 line5-same --- 1,7 ---- ! line1-mod line2-same ! line3-mod line4-same line5-same + line6-append + line7-append
1 | 字符符号说明: ! (修改) + (添加) - (删除)、空白 (未变更)。del1 (文件内容) 是修改跟前面 3,5c3 虽然一致,但是并没有同时列示该组修改情况,并不知道 del1 实际上是删除,
采用 -c 需注意该问题,! 可能是删除 (注:选项 -u 则会标示成删除 - )。 |
-n
(RCS format) 以新文件的角度列出修改情况diff -n org.txt new.txt
d1 1 (1) a1 1 (2) line1-mod d3 3 (3) a5 1 line3-mod d7 2 a9 2 line6-append line7-append
1 | 采用 -n 是以新文件的角度列示, d1 1 在第 1 行删除 1 行。 |
2 | a1 1 在第 1 行添加 1 行,不会有修改的情况,「修改」为先「删除」再「添加」。 |
3 | del1 (文件内容) 为删除,以新文件的角度列示;不关心源文件,只列出 d3 3 在 3 行删除 3 行。 |
patch 补丁
patch [OPTION]... [ORIGFILE [PATCHFILE]]
|
输出补丁后的文件至 FILE。 |
|
读取 PATCHFILE 补丁文件 (取代标准输入 |
|
回复补丁 (已补丁的文件以 PATCHFILE 回复成补丁前的内容)。 |
diff
将 org.txt
及 new.txt
产生补丁档 org.patch
diff -u org.txt new.txt > org.patch (1)
1 | 注意!diff 中的 -unified[NUM] 一并列出未变更的行数,不应设置 0,若补丁只有添加时,重复运行可能不会引发错误。另外 org.patch
即为前面 Unified context 内容, |
org.txt
以 org.patch
补丁patch org.txt org.patch
org.txt
以 org.patch
补丁,输出至另一个文件 orgmod.txt
patch org.txt -i org.patch -o orgmod.txt
orgmod.txt
跟 new.txt
应该相同 (即无输出).diff -u orgmod.txt new.txt
-R
,将 orgmod.txt
回复成 org.txt
patch orgmod.txt -R -i org.patch
orgmod.txt
跟 org.txt
应该相同diff -u orgmod.txt org.txt
输入与输出重新导向
输入与输出 (I/O) 重新导向是 Linux 系统中非常重要的功能,能够任意组合各种命令的输入和输出及串接任意的「命令管道」(command pipeline)。
在运行命令时,先创建好输出管道,再创建输入管道及串接管道。(大部份的命令在) 处理时并非将输入全部读取,而是读取一定的数据量,参与管道的命令「平行处理」输入与输出。
>
、>>
管道输出-
ls > output.txt (1) date >> output.txt (2)
1 将 ls「标准输出」至 output.txt 文件,这里为什么称为 「标准输出」,因为命令的输出事实上有「标准输出」及「错误输出」。 2 把 日期
输出附加在文件尾端 (如果文件不存在,则会创建新文件)。 <
管道输入-
cat < input.txt (1) cat < input.txt > output.txt (2)
1 cat 取得 (由管道输入) input.txt 数据后输出至主控台 (显示于屏幕上)。 2 cat 取得 input.txt 数据后,标准输出至 output.txt。
一般情况不会这样写,会采用由命令读取文件的方式cat input.txt > output.txt
。当输入文件跟输出文件相同时,如果以下列方式运行:cat file.txt > file.txt
将得到一个空的
file.txt
,其原因在于创建管道时,输出管道> file.txt
会先运行将创建一个空的file.txt
。 <<
管道输入终止字符串-
cat > output.txt (1) cat << EOF (2) ... EOF
1 cat 需要标准输入管道,在没有重导的情况下,表示由主控台 (键盘) 输入,直到输入终止字符 Ctrl+d。 2 由主控台输入,直到输入终止字符串 EOF
。终止字符串,可任意命名。line1='I am the first row' line2='I am the second row' cat > output.txt << EOF (1) $line1 $line2 EOF (1)
1 终止字符串没有双 (单) 引号的情况下会替换变量。 output.txt 的内容如下I am the first row I am the second row
接上例,把 EOF 改成
"EOF"
或者'EOF'
cat > output.txt << "EOF" (1) $line1 $line2 EOF
1 终止字符串有双 (单) 引号的情况下不会替换变量。 output.txt 的内容如下$line1 $line2
另外可不采用双 (单) 引号的终止字符串,以反斜线 (\) 禁止转译变量。cat > output.txt << EOF \$line1 \$line2 EOF
|
串接管道-
串接命令操作字符
|
将多个命令串接。串接前一个命令的正确输出管道;并不能处理错误的管道输出。命令处理后,再传递给下一个命令作为标准输入。串接管道的运行顺序是由左至右。ls | cat -n (1) ls | cat -n | grep -P '1\t' > output.txt (2)
1 ls
输出给cat -n
加上行号后输出至主控台。2 串接多个「命令管道」后标准输出至 output.txt,输出管道最先运行 (创建),串接管道的运行顺序是由左至右,先运行 ls
、cat -n
再运行grep -P '1\t'
。输入及输出管道 (各别) 最多只能一个,不可能有多个,下列是将ls
输出至cat
文件。ls > cat -n > output.txt
标准及错误输出
- 一般的 Linux 命令会有三个输入与输出的管道,分别为:
-
-
标准输入 (
stdin
,代号 0):程序输入管道。
注:一般命令都具有读取文件的功能,读取文件并不需要采用<
来读取。 -
标准正常输出 (
stdout
,代号 1):命令正常输出管道。 -
标准错误输出 (
stderr
,代号 2):命令出错或状态消息 (可能) 以错误管道输出。
-
- Linux 特殊文件:
-
-
/dev/null
是 Linux 空设备,写入这个文件的数据会被直接丢弃,如果从这个文件读取数据,则会像读取空文件一样。 -
/dev/stdout
标准正常输出,即为主控台。 -
/dev/stderr
标准错误输出,也是主控台。
-
ls
列出不存在的文件输出至 output.txt
$ls nonexistent > output.txt ls: cannot access 'nonexistent': No such file or directory
上述的错误消息就是来自于 ls
的标准错误输出,output.txt
文件也会创建,不过内容是空的,因为命令没有任何标准正常输出。
输出管道可以采用操作符把正常管道 1>
输出至指定设备,或者是错误管道 2>
的输出设备。
注:标准输出管道 1>
可不需要指定操作符,1>
跟 >
相同。
ls
列出不存在的文件输出至 output.txt
,错误输出至 error.txt
ls nonexistent 1> output.txt 2> error.txt
ls 1> output.txt 2> error.txt nonexistent
运行后,主控台看不到任何消息。
error.txt
ls: cannot access 'nonexistent': No such file or directory
>&
或 &>
,将消息全部写入 all.txt
:ls output.txt nonexistent &> all.txt
all.txt
ls: cannot access 'nonexistent': No such file or directory output.txt
/dev/null
,不会得到任何消息。ls output.txt nonexistent &> /dev/null
- 合并管道
-
在运行命令时,可先设置合并管道。
2>&1
,将管道 2 导入管道 1。
1>&2
,将管道 1 导入管道 2。
要注意 linux 创建输出管道的顺序,是最右边先创建,「合并管道」要最先运行。
ls output.txt nonexistent 1> all.txt 2>&1
all.txt
的内容跟前面的「所有消息在 all.txt
」一样。
ls output.txt nonexistent 2>&1 1> all.txt (1)
1 | 在主控台可看到错误消息,因为顺序不正确。合并管道 2>&1 要最先运行才有作用 (创建输出管道的顺序,是最右边先创建)。 |
- 输出重导至标准输出发生权限错误
-
$echo 123 > /dev/stdout bash: /dev/stdout: Permission denied $echo 123 > /dev/stderr bash: /dev/stderr: Permission denied
当登录为 user1 以 su 切换至另一个 user2 用户,是造成本问题的原因su user2
dev/stdout
是一个符号链接到/proc/self/fd/1
,再以符号链接至伪终端,例如:dev/pts/1
。伪终端权限是在登录时授予,当以su user2
切换至不同的帐户时,伪终端的拥有权并不会更改,user2
没有写入权限。
注:su root
不会错误,超级用户不受权限影响。user2
的伪终端权限$ls /dev/stdout /proc/self/fd/1 /dev/pts/1 -lU lrwxrwxrwx 1 root root 15 2023-03-10 04:25 /dev/stdout -> /proc/self/fd/1 lrwx------ 1 user2 user2 64 2023-03-15 11:58 /proc/self/fd/1 -> /dev/pts/1 crw--w---- 1 user1 tty 136, 1 2023-03-15 11:58 /dev/pts/1
文件内容查阅
cat 显示文件所有内容。 head 显示文件开头的内容。 tail 显示文件尾端的内容。 more 一页一页向后显示内容 (可向上翻页仅限文件,管线无作用)。 less 与 more 类似,但比 more 更容易操作,可前后翻页。
上述的命令与本文编辑器 (例如 nano 或 vim) 相比,启动时不需要读取整个文件,加载时间会大大缩短,可用于打开大文件。
cat [参数] [文件] -n 打印出行号 -E 将行尾的断行字符以 $ 显示 -T 将字符 tab 以 ^I 显示
head -n20 /var/log/auth.log -n 20, 显示 20 行,缺省为 10 行。
tail -n20 -f /var/log/auth.log
-n 20, 显示 20 行,缺省为 10 行。
-f 持续监控文件内容,当有新数据时即时显示。离开监控模式需按下 Ctrl+c 中断监控。
more 查看命令
more /var/log/auth.log
Shortcut | Purpose |
---|---|
q |
离开 more |
h |
显示说明 |
Enter |
向下一行 |
空白键 或 f |
向下翻页 |
b 或 Ctrl+b |
向上翻页 (仅限文件,管线无作用) |
/ 字符串 |
向前搜索「字符串」 |
n |
重复上一个搜索 (向前),跟 / 有关。 没有向后的功能。 |
less 查看命令
less 一次显示一页文件或命令输出 (pipe) 的内容,跟 more 相似但具有更好的功能;如可翻页内容。
less /var/log/auth.log
rsync --help | less
Shortcut | Purpose |
---|---|
q |
离开 less |
h |
显示说明,离开说明则按下q。 |
PageDown 、 空白键 或 f |
向下翻页 |
PageUp 或 b |
向上翻页 |
g |
至文件开头 |
Shift+G |
至文件尾端 |
/ 字符串 |
向前搜索「字符串」 |
? 字符串 |
向后搜索「字符串」 |
n |
重复上一个搜索 (向前),跟 / ? 有关。 |
Shift+N |
反向重复先前的搜索 (向后),跟 / ? 有关。 |
- i |
切换搜索是否区分大小写,缺省为区分大小写。 |
- N |
切换是否显示行号 |
grep 找出符合模式的「行」
grep [选项]... PATTERN(模式) [文件]...
Pattern selection and interpretation: |
|
|
以 PATTERN 进行匹配 |
|
PATTERN 为延伸正规表示法 (ERE) |
|
PATTERN 匹配单词,如匹配 word,words 则不匹配。 |
|
不区分大小写 |
Miscellaneous: |
|
-v, --invert-match |
反向匹配,找出不合乎符合模式的「行」。 |
Output control: |
|
|
递归,含目录内的所有文件 |
|
打印行号 |
|
将字符 tab 以 |
|
仅列出文件内容符合模式的文件名 |
|
仅搜索 GLOB 匹配 FILE_PATTERN 的文件 |
Context control: |
|
|
列出匹配前 NUM 行数 |
|
列出匹配后 NUM 行数 |
grep 'Pattern1\|Pattern2' file...
grep -E 'Pattern1|Pattern2' file...
grep -rl PATTERN
/etc
目录内的特定文本 (hosts
):grep -rw hosts /etc
grep
如果按语法顺序,可不需要 -e
选项,但习惯在把路径写在前面,则加入 -e
选项,并把表示法加上单引号比较清楚。grep /etc -e 'hosts' -rw
/etc
目录内特定扩展名 (GLOB 匹配) 中的单词 (w
) 文本 (hosts
):grep /etc -e 'hosts' -rw --include=*.allow --include=*.deny
grep /etc -e 'hosts' -rw --include=*.{allow,deny}
cut 截取部份字符或字段
cut 选项... [文件]...
|
以定界字符区分出字段,截取字段。 |
|
截取字符。 |
|
截取字节。 |
|
定界字符,缺省为制表字符 (Tab 键),只允许一个字符。 |
|
补集参数,将指定的部份删除,留下剩余的部份。 |
|
将定界字符取代成 STRING |
|
只打印具有定界字符的行。 |
-f
、-c
及 -b
的 LIST 的参数可以是整数、以逗号分隔的多个整数,或者是范围、以逗号分隔的多个范围。
|
第 n 个字段、字符或字节。 |
|
第 n 个字段、字符或字节到 (该行的) 结尾。 |
|
由第 n 至第 m 个字段、字符或字节。 |
|
由第一个至第 m 个字段、字符或字节。 |
- 选项
-c
,截取字符 -
如截取前面 6 个字符为
1-6
,截取第 7 个字符至结束如7-
。数据如下$grep ubuntu /etc/passwd ubuntu:x:1000:1000::/home/ubuntu:/bin/bash
截取字符-c
范例grep ubuntu /etc/passwd | cut -c 1-6 (1) grep ubuntu /etc/passwd | cut -c -6 (1) grep ubuntu /etc/passwd | cut -c 7- (2) grep ubuntu /etc/passwd | cut -c 1-6 --complement (3)
1 截取前面 6 个字符 ubuntu
2 截取第 7 个字符至结束 :x:1000:1000::/home/ubuntu:/bin/bash
3 去掉前面 6 个字符,留下剩余的部份。 :x:1000:1000::/home/ubuntu:/bin/bash
- 选项
-d
指定定界字符 -
以选项
-d
指定定界字符:
,将数据标示出字段如下:ubuntu:x:1000:1000::/home/ubuntu:/bin/bash 1 :2:3 :4 ::6 :7
定界字符-d
为:
,截取字段-f
grep ubuntu /etc/passwd | cut -d : -f 1,6 (1) grep ubuntu /etc/passwd | cut -d : -f 1,6 --output-delimiter=' ' (2)
1 截取字段 1、6。 ubuntu:/home/ubuntu
2 截取字段 1、6,将定界字符取代成空白。 ubuntu /home/ubuntu
-s
) 的行ls /bin -l | cut -d '>' -s -f 1,2
awk 找出符合字段的「行」
本文已移至 awk
sed
本文已移至 sed