我正在尝试创建一个 zip 函数,该函数将执行我在压缩文件或文件夹时通常执行的所有步骤。假设我当前的目录是~
,我想压缩一个名为 的文件夹Folder1
,其文件路径是~/Folder2/Folder1
。
发行
cd ~/Folder2 && zip -r Folder1 Folder1 && cd -
正是我想要的。也就是说,它进行压缩,以便输出Folder1.zip
不包含通向我正在压缩的文件夹(即/home/user/Folder2
)的文件夹,它递归地进行压缩,并且它接受 zip 的第一个参数,其名称与我要压缩的文件或文件夹的名称完全相同。正在拉拉链 ( Folder1.zip
)。
所以我想在我的.zshrc
东西中创建一个类似于
coolerzip() { cd /path/to/file && zip -r file file && cd - }
它只需要接受一个参数,在本例中,它将是~/Folder2/Folder1
。然后将是中Folder1
两个 s 的名称,我将在压缩之前直接进入当前目录中的so 。有什么方法可以实现这一目标,以便只需要一个参数而不是三个?file
coolerzip
cd
~/Folder2
Folder1
coolerzip
答案1
该函数的参数是$1
。
您可以使用历史扩展修改器提取目录部分和路径的最后一个组成部分:如果参数是~/directory2/directory1
则$1:h
is~/directory2
和$1:t
is directory1
。 (助记:h
ead 和t
ail。)
在函数体周围使用括号而不是大括号。这样函数体运行在子shell(一个单独的shell进程)中,变量赋值、目录更改等只影响子shell。
coolerzip () (
cd $1:h &&
zip -r $2:h.zip $2:h
)
其他 shell 没有历史扩展修饰符,因此您需要不同的东西来解析参数。对于文件名,${1##*/}
去掉所有前导目录组件;但是,如果参数中有尾部斜杠,则此方法不起作用,而"$(basename -- "$1")"
在这种情况下则有效。对于主要目录,请使用$(dirname -- "$1")
.请注意,在 zsh 以外的 shell 中,您需要在变量替换周围加上双引号。
coolerzip () (
name="$(basename -- "$1")"
cd "$(dirname -- "$1")" &&
zip -r "$name.zip" "$name"
)
答案2
我不是 zsh 用户,但以下内容在 bash 中有效,但我不这样做思考它使用任何特定的 bashisms,所以这应该可以完成工作:
coolerzip() { cd "${1%/*}" && zip -r "${1##*/}" "${1##*/}" && cd -; }
$1
是位置参数;在脚本或函数中它将引用第一的在命令行上给予脚本或函数的参数。您还可以使用$2
等等,最多$9
.$0
给出脚本或函数的名称(第零个参数),$@
给出除第零个参数之外的每个参数,并$#
给出参数的数量(同样,不包括第零个参数)。如果您从命令行调用(或任何 shell),事情的行为会有所不同sh -c
,但我不打算在这里讨论这一点。
${1%/*}
$1
返回被剥离的glob 模式的最短匹配的值*/
(如果您想要最长match 在末尾,使用%%
) ——这样它就会去掉你提供给函数的路径的最后部分。${1##*/}
删除*/
开头的模式的最长匹配$1
(对于开头的最短匹配,请使用单个#
)。
上面的功能有点脆弱;如果参数中有任何尾部斜杠(例如~/folder1/folder2/
),它将中断。如果参数是不包含任何斜杠的单个目录名称,它将以不同的方式中断。解决这个问题的一个简单方法是使用readlink
命令返回输入参数的完整路径(并且还删除任何尾部斜杠,至少在我的 Ubuntu 系统上)。
coolerzip() { a="$(readlink -f "$1")"; cd "${a%/*}" && zip -r "${a##*/}" "${a##*/}" && cd -; }