文件处理工具

切割和拼接

将一个文件分割为多块:

split [OPTION]... FILE PREFIX

PREFIX:输出文件名前缀,输出文件名自动添加后缀编号,形如:PREFIXaaPREFIXab、...。 FILE:输入文件名,如果未提供或为-则从标准输入读取(管道)。

选项:

-a:后缀长度; -d:使用数字编号,--numeric-suffixes[=FROM]允许指定起始编号; -x:使用十六进制编号,--hex-suffix[=FROM]

-b,--bytes=SIZE:每个输出文件的长度(字节),K,M,G,T,P,E,Z,Y (1024)或KB,MB,... (1000); -l,--lines=NUMBER:每个输出文件的行数; -n,--number=CHUNKS:指定输出文件的个数,l/N不在行内分割;K/N仅输出第K个分块到标准输出(l/K/N);==r/N将文本文件内容按行轮流输出到N个分块中==。

合并文件
cat [OPTION] ... FILE ...

将文件拼接并输出到标准输出,或使用输出重定向将内容输出到新文件。如果FILE未提供或为-则从标准输入读取(管道)。

diff and patch

用法

diff [options] origin_filename changed_file
diff [options] origin_dir/ updated_dir/      # 对比文件夹下的对应文件变更

diff文件模式:默认模式仅记录改动的位置信息和改动内容;

  • -c:copied context(补丁内容附带修改部分的前后内容,从而不仅依赖行号定位改动位置);

    -C N:指定上下文行数;

  • -u:unified context(修改内容直接对比,更加紧凑,GNU diff and patch)。

  • -y:side-by-side(输出两列对比)。colordiff不支持此模式的高亮。

空白对比处理:

  • -b,--ignore-space-change
  • -w, --ignore-all-space
  • -B, --ignore-blank-lines

升级补丁(patch)

diff输出内容可保存为补丁文件,利用patch程序可基于旧版本和补丁文件重建新文件。

patch originalfile -i patchfile.patch -o updatedfile #*
patch -p 0 -i patchfile.patch  # -p N 仅处理<=第N层子文件夹

*yum install patch

对于已分发文文件v1.file,如果要进行更新可选择生成补丁(diff v1.file v2.file > v12.patch),从而减小传输带宽;在远程机器上将补丁应用于修改后的文件(patch v1.file -i v12.patch -o v2.file)。对于被修改过的远程文件v1r.file,则这种更新方式会失败,因为补丁信息与基础文件不能匹配,因此需要人工将v1.file->v1r.file中的修改内容合并到v2.file中。

  1. Introduction to Using Diff and Patch | A Cloud Guru
  2. 读懂diff - 阮一峰的网络日志 (ruanyifeng.com)

Comparing and Merging Files (gnu.org)

高亮比较结果

diff origin changed | colordiff # => colordiff origin changed *
diff origin changed | vim -R -  # 在Vim中显示diff结果
vim -d origin changed           # => vimdiff 在Vim中显示对比结果,显著高亮行内不同部分。
git diff --no-index --word-diff=color origin changed  # **

*yum install colordiff:高亮比较结果。

**--no-index比较的文件不在git仓库中时使用。

归档

tar -[cruxt][z][v] -f path/archive.tar.gz \
   -C /file/path \ # 更改操作目录
   file1 file2 ...
操作模式

-c,--create:从选定的文件创建新的档案(覆盖已有同名档案);

当不声明压缩格式选项-z时(且文件扩展名为.tar或添加--no-auto-compress选项),只进行归档而不执行压缩。

-r,--append:将选定文件追加文件至档案末尾(不会覆盖同名文件);

-u,--update:追加文件至档案,覆盖档案中较旧的文件;

-t,--list:列出档案内容;

-x,--extract:提取档案中的文件(到当前目录),使用-C指定提取文件的存储目录;

-A :追加tar文件合并至档案末尾(--catenate, --concatenate);

--delete:从档案中删除文件;

tar -f archive.tar --delete test2.txt
文件

-f,--file=ARCHIVE:选择操作的目标档案文件;-T,--files-from=FILE:从文件读取进行操作的文件列表。

-C,--directory=DIR:更改操作目录。对于归档操作,该选项影响后续源文件的根目录;对于提取操作,该选项影响提取内容的存储目录。

-h,--dereference:压缩时读取符号链接指向的目标文件内容==替换符号链接==;如果压缩时未指定-h,则保留符号链接信息,解压缩时还原为符号链接。(相应地,--hard-dereference对于hardlink文件似乎没用)。

--strip-components=1:移除档案中的目录层级(==为了修改根目录名而自行创建根目录==);

--add-file=FILENAME:添加包含特殊字符的文件。

--exclude=PATTERN:排除文件的模式;-X,--exclude-from=FILE:从文件中读取排除文件的多个模式;

--exclude="*.pyc" --exclude="*tmp/*" --exclude="*model/*" --exclude="*output/*"

-N, --newer=DATE-OR-FILE, --after-date=DATE-OR-FILE:仅存储比所给日期或文件更新的文件(包括所给定日期的文件)。

-p,--preserve-permissions:保留文件访问权限。

压缩

-z:等效于对归档后的文件/文件夹,使用gzip压缩或解压文件,输出文件扩展名为.tar.gz

tar -cvf archive.tar FILES ...
gzip --keep archive.tar # >> archive.tar.gz
信息

-v:列出所处理的文件。

文件覆盖

-k, --keep-old-files:不覆盖文件,提示错误(默认为覆盖),--skip-old-files直接跳过,不产生错误。 --keep-newer-files :不覆盖本地更新的文件(本地存在相同时间或更新时间的同名文件时输出提示)。 --overwrite:提取时覆盖已有文件。 --remove-files:归档后删除原文件。

https://www.rootusers.com/23-tar-command-examples-for-linux/

压缩/解压

gzip

gzip filename       # 压缩*
     -c,--stdout    # 输出到标准输出, 保留源文件
     -k,--keep      # 保留输入文件
     -f,--force     # 强制覆盖输出文件  
     -r,--recursive # 递归遍历文件,并分别执行压缩**
     -1,--fast
     -9,--best
gzip -l,--list filename # 列出压缩内容的信息

如果未指定文件名,或文件名为-,从标准输入读取数据。

*gzip默认进行压缩操作,指定-d,--decompress执行解压任务(等效于调用gunzip)。

**gzip 只支持压缩文件,不支持文件夹;使用-r选项会对文件下的文件分别进行压缩;使用tar对文件夹归档后再进行压缩。

zip

# sudo apt install zip unzip
zip [options] archive[.zip] INPATH1 INPATH2 ... 
  # -可替代使用标准输入/输出分别代替输入(文件名)/输出(压缩内容), 
  # 使用-代替输入会将输出定位到标准输出; -@则仍将压缩内容输出至文件; 
  -r,--recurse-paths  # 默认至包括给定的目录/文件,不包含子目录内容
  -x,--exclude file_pattern # 排除文件  -x@exclude.lst
  -i,--incldue        # 指定输入
  -y,--symlinks       # 存储符号链接而非其指向的文件
  --out,--output-file # 不更新已有zip文件而是输出到新文件
  -FS,--filesync      # 源和zip文件同步模式
  -P,--password password
  -du,--display-usize # Display the uncompressed size of each entry.
  -z,--archive-comment # 从标准输入/文件(<conmment_file)读取注释
  -Z,--compression-method=store|deflate|bzip2 # 压缩方法
  -N  # N=0-9 0表示不压缩(-Z store)
zip add|update|freshen|delete|copy ...
  # "update" (-u,--update)
  # "freshen" (-f,--freshen) only update existed files, not add new files. 
  # "delete" (-d,--delete)
  # "copy" (-U,--copy-entries) 从zip文件中选取文件并输出到新的zip文件(--out)
unzip -O GB2312 file.zip -d dir  
      -l FILE # 仅列出包含的文件的信息
      -z FILE # 仅列出压缩包的注释信息
      -P password

如果出现文件名乱码:-O指定Windows压缩文件使用的编码方案;-I指定UNIX或其他系统下的编码方案。

zip在操作时会先创建一个临时文件,仅当

zip可对压缩文件进行分片,从而方便大文件的传输。unzip无法直接对分片的压缩文件进行解压,可首先将其拼接(cat)为一个文件再执行解压。

  A split archive is a standard zip archive split over multiple files.  (Note that split archives are not just archives split in to pieces, as the offsets of entries are now based on the start of each split. Concatenating the pieces together will invalidate these offsets, but unzip can usually deal with it. zip will usually refuse to process such a spliced archive unless the -FF fix option is used to fix the offsets.
   When changing an existing zip archive, zip will write a temporary file with the new contents, and only replace the old one when the process of creating the  new  version  has  been completed without error.
zip -s 700m ARCHIVE.zip --out ARCHIVE-SPLIT.zip   # 将字zip文件分片(-s,--split-size)
# ARCHIVE-SPLIT.z01, ARCHIVE-SPLIT.z02, ..., ARCHIVE-SPLIT.zip.
# k (kB), m (MB), g (GB), or t (TB) (the default is m)
zip -s 0 input-split.zip --out input-unsplit.zip  # 将分片文件合并

还支持将一种分片容量的输入改变为另一种分片容量进行输出(中间过程可能需要恢复为完整文件)。

主机之间复制文件

scp

scp命令(secure copy)用于Linux之间复制文件和目录,是linux系统下基于ssh登录进行安全的远程文件拷贝命令。scp是加密的,scprcp (不加密的)加强版。

scp [options] file user@dest_host:file # local to remote
scp [options] user@src_host:file file  # remote to local

-P:指定远程服务器端口号。

注意:使用scp命令要确保使用的用户具有可读取远程服务器相应文件的权限,否则scp命令是无法起作用的。

scp可以在源与目的主机以外的第三台主机执行,只需保证源与目的主机间有相应地读写权限。

rsync

rsync常用于文件备份和镜像,支持本地和远程目标之间的文件传输。对于目标路径已有的文件,仅传输源和目标文件的差异部分;并且支持只更新较新的文件。rsync默认检测文件的修改时间和大小,如果未发生变化,则仅修改目标文件的相关属性信息。rsync会对传输文件按文件名排序。

==目标目录如果不存在==,rsync会自动创建。

rsync支持两种模式:远程shell(如ssh,目标形如user@host:path);rsync daemon(目标形如user@host::pathrsync://)。rsync==必须安装在收发两台机器==。

启动rsync daemonman rsyncd.conf

rsync -rua srcfiles ... user@host:path  # files支持通配符
rsync -ua --delete source/ target       # source->target同步
文件路径格式
  • ==如果源路径为目录且以/结尾则只拷贝目录下的内容到目标目录;反之,将该目录拷贝到目目录下(目标目录后是否有/无影响)==;
  • 如果源路径为文件,目标路径为目录,则将该文件保存到目标目录下;如果目标路径为文件,则保存为目标文件。

文件传输控制

-a,--archive:归档模式,保证文件属性保留,等效于 -rlptgoD

  • -r:递归复制子目录内容,若未指定该选项,将跳过提供的文件夹;-d,--dirs只拷贝==当前目录==,不包含目录内容(除非目录名为.或以/结尾);如果同时出现,-r优先级高于-d
  • -l,--links符号链接不转换为实际文件;-L,--copy-links将符号链接转换为实际文件。
  • -t,--times:保留文件的时间信息。
  • -g,--group;-o,--owner:保留文件的用户信息。
  • -D,--devices --specials:传输字符或块设备文件和特殊文件(如明明套接字和FIFIO)。

-v,--verbose:打印传输过程信息,可叠加最多两个-v以增加输出信息量。

--progress:显示传输进度信息。

-R,--relative:保留源文件参数给出的路径并拼接到目标路径下。

-c,--checksum:使用文件大小和校验和(MD5)而非修改时间检查文件是否更改。由于收发两端都需要读取文件计算校验和,因此处理速度较慢。

-z,--compress:压缩传输内容; --compress-level=NUM

-b,--backup:目标位置已存在的文件和目录将被重命名; --backup-dir=DIR, --suffix=SUFFIX

-n,--dry-run:与-v-i结合使用。

如果未指定目标路径,则列出源文件(类似于ls -l,源也可以是远程)。如果源和目的都为本地路径,则在本地路径间进行复制。

目标文件权限控制
  • -p,--perms:目标文件的权限信息与源文件保持一致。如果未指定该选项:已有文件再更新时权限信息不变;新文件的普通权限标志位与源文件一致,其他的继承自接收目录的默认权限。
  • -E,--executability:在未启用--perms时,为普通文件添加可执行权限(启用时忽略该选项)。
  • --chmod=u=rw,go=r,D+x:该选项修改来自源文件的权限信息(而非已保存在本地的文件权限),因此未启用--perms,则对已有文件无影响。除chmod的权限声明方式外(也支持数字模式--chomd=F644,D755),可添加额外的前缀:D表示仅应用于目录,F表示仅应用于普通文件。

同步条件选项

-u,--update:跳过目标路径下修改时间比源文件新的文件。 --delete:删除目标路径下,不存在于发送方的内容,与发送方保持一致(镜像)。 --existing, --ignore-non-existing:只同步目标已存在的内容; --ignore-existing:只同步目标不存在的内容。 --exclude=PATTERN:排除无需同步的文件(收发双方同时忽略),可多次使用该选项;--exclude-from=FILE从文件指定多个模式;文件中的空行、以’;’’#’开头的行被忽略。

foo   # 包含foo的路径
/foo  # 匹配传输目录下以foo开头的文件路径
foo/  # 仅匹配目录
*     # 匹配任何内容直到"/"
**    # 匹配任何内容
?     # 匹配除了"/"以外的字符
[]    # 定义匹配字符集合

--include=PATTERN--include-from=FILE:指定要包括的文件,优先级高于--exclude--files-from=FILE:确切指定要传输的文件。

增量备份

第一次同步是全量备份,所有文件在基准目录里面同步一份。其后每次使用最近的备份目录作为基准目录,只同步源目录与基准目录之间有变动的部分并将其保存到新的目标目录;没有变动的文件都是指向基准目录文件的==硬链接==(不能生成软链接,否则后期对比时与源文件不同)。

rsync -a --delete --link-dest=COMPARE_DIR /source/path /target/path

--copy-dest=DIR:直接从基准目录DIR复制未发生变化的文件(而非创建链接),减少网络传输量。通过复制而非创建硬链接保证对基准目录的修改不会影响目标目录内容。 --compare-dest=DIR:仅复制与基准目录DIR相比发生变化的文件,并删除目标目录下已存在于DIR中未发生变化的文件。==利用该选项可以找出两个版本之间的差异文件(相当于文件级别的diff)==。

rsync -a --delete --compare-dest=LastVersion LastestVersion AddedFiles
rsync -a --delete --compare-dest=LastestVersion LastVersion RemovedFiles

rsync 用法教程 - 阮一峰的网络日志 (ruanyifeng.com)

cwrsync

cwrsync是基于cgywin开发的rsync软件。cwrsync 5.5 包含rsync 3.1.2(与CentOS7.x rsync版本兼容),cwrsync 6.2.4包含rsync 3.2.3

配置cwrsync执行脚本
SET CWRSYNCHOME=C:\apps\cwRsync_5.5.0_x86_Free
SET PATH=%CWRSYNCHOME%\bin;%PATH%

如果系统中未安装其他SSH客户端,可将%CWRSYNCHOME%\bin配置到用户路径中。

配置免密码远程访问

如果系统已经使用Open-SSH客户端,并生成密钥且已配置远程SSH免密码访问。则将~/.ssh/目录下的id_rsa复制到%CWRSYNCHOME%/home/%USERNAME%/.ssh目录下,并将其访问权限设置为仅限当前用户。

如果系统未使用Open-SSH客户端,则使用cwrsync自带SSH客户端程序ssh-keygen生成密钥并分发给远程机器。

文件访问权限配置

由于Windows与Linux的文件访问权限设置方式不一致,容易导致向Linux系统同步时目标系统文件权限不正确。因此执行rsync命令时配置以下选项(关闭保持权限的选项,并显式设置目标系统的访问权限):

rsync -urltDv --delete --chown USER:GROUP --chmod a+rX,u+w,go-w SOURCE TARGET