递归更改目录并解压缩文件 - linux

时间:2020-12-18 22:22:57

标签: linux bash recursion 7zip

我有几个压缩文件,它们在使用各种压缩格式的子目录中嵌入/嵌套了压缩文件,例如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”循环。

1 个答案:

答案 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)而不是使用 -execxargs 将获取 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
相关问题