我正在尝试制作一个脚本,该脚本将查看该目录是否存在,并根据目录的名称/路径将其所有内容压缩到该目录下。
我能走的最远是——
#!/system/bin/sh -xv
Z="$PWD/../WorkingDir";
T='320';
F='480';
I='540';
D='dark';
L='light';
P='play';
cd $Z;
if [ -d $T/$D ]; then
R=""$T"_"$D".zip";
else
if [ -d $T/$L ]; then
R=""$T"_"$L".zip";
else
R="file.zip";
fi
fi;
for dir in */*/; do
#Skip directories where the zip already exists
[ -e "$dir"/"$R" ] ||
( cd -- "$dir" && zip -0rq "$R" .)
done
但这种情况发生了——
#!/system/bin/sh -xv
...
.
.
if [ -d $T/$D ]; then
R=""$T"_"$D".zip";
else
if [ -d $T/$L ]; then
R=""$T"_"$L".zip";
else
R="file.zip";
fi
fi;
+ [ -d 320/dark ]
+ R=320_dark.zip
for dir in */*/; do
#Skip directories where the zip already exists
[ -e "$dir"/"$R" ] ||
( cd -- "$dir" && zip -0rq "$R" .)
done
+ [ -e 320/dark//320_dark.zip ]
+ cd -- 320/dark/
+ zip -0rq 320_dark.zip .
+ [ -e 320/light//320_dark.zip ]
+ cd -- 320/light/
+ zip -0rq 320_dark.zip .
.
.
...and so on..
每个文件的名称都相同(320_dark.zip在这种情况下)。我希望每个压缩的文件都不同(根据文件夹名称/路径)。
我想了 -
+ [ -d 320/dark ]
+ R=320_dark.zip
- 每次更改每个文件夹。就像320_light.zip
文件夹路径应该一样320/light
。
所以输出的最后一部分是 -
+ [ -e 320/dark//320_dark.zip ]
+ cd -- 320/dark/
+ zip -0rq 320_dark.zip .
+ [ -e 320/light//320_light.zip ]
+ cd -- 320/light/
+ zip -0rq 320_light.zip .
答案1
这是我的建议,为了保持一致性,删除单字母变量并更改存档的位置:
#!/system/bin/sh -xv
cd "$PWD/../WorkingDir"
compress() {
# Detect only known dir names, convert slash to underscore
local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"
# Set a default value to the variable
: ${arch:=file}
# Only create a ZIP archive if not present in the parent directory
# Note $PWD is evaluated *before* cd
[ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
}
for dir in */*/; do
compress $dir
done
只需更改该sed
行以添加我所说的“众所周知的目录名称”即可。
编辑:根据OP的要求添加一些解释。
每次循环找到新目录时,脚本都会在压缩目录之前验证条件for
。变量也被消除了。让我们剖析一下代码。
主循环
cd "$PWD/../WorkingDir"
for dir in */*/; do # Ensures to select only directories
compress $dir # compress runs some checks prior to compressing
done
对此确实没什么可说的。
例行公事compress
local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"
$1
是传递给 的参数compressed
,即要检查和压缩的目录。sed
首先 ( '/320\/(light|dark)/'
) 检查路径是否为以下形式
320/light
320/dark
并返回斜杠转换为下划线的路径:'s@/@_@g'
。使用 at 符号作为分隔符以提高可读性,避免转义斜杠。其他有效的符号是's:/:_:g'
or's#/#_#g'
或 经典的's/\//_/g'
。请注意如何使用反斜杠转义要转换的斜杠。我发现后一种形式的可读性较差。
尾随p
与sed -n
;一起使用。在这种特殊情况下,后一个选项意味着“p
除非找到匹配项(即在包含的斜杠中),否则不要回显任何内容»。因此arch
将包含一个斜杠转换为下划线的路径当且仅当320\/(light|dark)
在路径中找到正则表达式。否则它不会回显任何内容,形成arch
一个空白变量。
Option是告诉使用规范正则表达式的-r
便捷方式,更具可读性。sed
否则,您将需要转义括号和管道字符。我发现比or'/320\/(light|dark)/s@/@_@gp'
更具可读性。'/320\/\(light\|dark\)/s@/@_@gp'
'/320\/\(light\|dark\)/s/\//_/gp'
: ${arch:=file}
如果该行为空,则设置arch
为其默认值“file”。需要这种奇怪的构造,因为${arch:=file}
单独构造会触发语法错误。冒号告诉 shell 不执行任何操作 ( ),但如果为空则:
分配一个值。arch
[ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
这里我使用了-f
not ,-e
因为前者也会检查零长度文件。仅当 ZIP 存档存在时测试才会成功和具有非零长度。
如果父级(或脚本的当前的) 目录,或者如果其大小为 null,则脚本会生成一个子 shell,该子 shell 会更改作为参数传递的目录compress
并压缩其内容。请注意,变量$1
和$PWD
被评估前子 shell 执行其指令,即$PWD
等于$Z
初始版本中的父目录。
扩大过滤器
您可以按照sed
以下方式进行操作:
sed -rne '/320\/(light|dark|play)/s@/@_@gp'
检查目录名称,例如
320/light
320/dark
320/play
您还可以考虑/(320|480|540)\/(light|dark|play)/
,它为您提供 9 种组合,或更通用的形式/[0-9]+\/(light|dark|play)/
(任何数字后跟斜杠和“之一”光“,”黑暗的“ 和 ”玩") 或什至/[0-9]+\/\w+/
(任何数字后跟一个斜杠和一个单词,又名[A-Za-z0-9_]+
)。这完全取决于您希望过滤器的严格程度或广泛程度。
答案2
#!/system/bin/sh -xv
Z=/absolute/path/to/WorkingDir
T=320
F=480 # ?
I=540 # ?
D=dark
L=light
P=play # ?
cd $Z
for dir in $Z*/*/; do
if [ -d $Z/$T/$D ] && [ ! -f $T$D.zip ]; then
zip -0rq $T$D.zip $dir;
elif [ -d $Z/$T/$L ] && [ ! -f $T$L.zip ]; then # elif rules
zip -0rq $T$L.zip $dir;
# It's not very efficient to scale this up, but you could add more elif statements here.
elif [ -d $Z/$F/$D ] && [ ! -f $F$D.zip]; then
zip -0rq $F$D.zip $dir;
# and so on..
else
exit
fi;
done
我想这就是你所需要的。如果需要任何调整,请告诉我。