我有几个压缩文件,它们在使用各种压缩格式的子目录中嵌入/嵌套了压缩文件,例如7z,拉链,焦油。如果我使用以下方法(见下文)递归解压缩它们,所有文件都将解压缩到我启动命令的根目录。由于这些压缩文件都不在我的控制之下(我没有创建它们),因此它们在存档时没有保留原始目录结构。因此,我不得不在解压缩它们之前找到为什么要对它们所在的子目录执行“cd”更改目录。
这就是我现在要做的事情...
$ find . -type f -name "*.zip" -exec 7z x -r -spe -tzip '{}' \;
$ find . -type f -name "*.7z" -exec 7z x -r -spe '{}' \;
如果找到压缩文件的位置并在该位置解压缩,我该如何进行“cd”操作?我认为通过附加检查和命令需要某种“while”循环。
答案 0 :(得分:1)
find . -type f -name "*.zip" -print0 | xargs -0 -I @ bash -c 'cd $(dirname "@"); 7z x -r -spe -tzip $(basename "@")'
find . -type f -name "*.7z" -print0 | xargs -0 -I @ bash -c 'cd $(dirname "@"); 7z x -r -spe $(basename "@")'
这使用 dirname
命令提取文件的目录,使用 basename
命令提取文件名本身。
为了确保这是安全的并且可以处理包含空格的文件名,我们打印以空字符结尾的字符串(-print0
加上 xargs -0
)而不是使用 -exec
。 xargs
将获取 stdin
中的所有行并调用给定的命令行,这里调用 bash
对目录执行 cd
,然后对文件名本身执行 unarchive 命令.
如果您没有安装 dirname
/basename
实用程序,而且看起来您没有安装,您也可以使用它(注意:这不适用于 find /
) :
find . -type f -name "*.zip" -print0 | xargs -0 -I @ bash -c 'fname="@"; base="${fname##*/}"; dir="${fname%/${base}}"; cd "${dir}"; 7z x -r -spe -tzip "${base}"'
find . -type f -name "*.7z" -print0 | xargs -0 -I @ bash -c 'fname="@"; base="${fname##*/}"; dir="${fname%/${base}}"; cd "${dir}"; 7z x -r -spe "${base}"'
这有点复杂。首先,我们需要将值 xargs
读取(@
,由 xargs
-I
选项指定)分配给变量以进行操作。注意:如果文件名包含引号或转义序列,这将不起作用,我相信它不会。 ${fname##*/}
将删除包括左侧最后一个斜杠在内的所有内容,从而删除目录并形成“基本名称”。这被分配给 $base
。目录是不是基础的所有内容,因此我们从原始文件名 (${fname%/${base}}
) 中删除基础并将其称为 $dir
。我们将目录更改为感兴趣的目录并取消归档基本名称。
[eje@localhost recurse-cd]$ ls -R
.:
a b
./a:
a a.zip b c
./a/a:
a-a.zip
./a/b:
a-b.zip
./a/c:
a-c.zip
./b:
a b b.zip
./b/a:
b-a.zip
./b/b:
b-b.zip
[eje@localhost recurse-cd]$ find . -type f -name "*.zip" -print0 | xargs -0 -I @ bash -c 'cd $(dirname @); unzip $(basename @)'
Archive: a-a.zip
extracting: a-a
Archive: a-b.zip
extracting: a-b
Archive: a-c.zip
extracting: a-c
Archive: a.zip
extracting: a-file
Archive: b-a.zip
extracting: b-a
Archive: b-b.zip
extracting: b-b
Archive: b.zip
extracting: b-file
[eje@localhost recurse-cd]$ ls -R
.:
a b
./a:
a a-file a.zip b c
./a/a:
a-a a-a.zip
./a/b:
a-b a-b.zip
./a/c:
a-c a-c.zip
./b:
a b b-file b.zip
./b/a:
b-a b-a.zip
./b/b:
b-b b-b.zip