递归更改目录并解压缩文件 - linux
Recusively change directory and unzip files - linux
我有几个压缩文件,它们的子目录中有 embedded/nested 个压缩文件,使用各种压缩格式,例如7z,邮编,tar。如果我使用以下方法(见下文)递归解压缩它们,所有文件都将解压缩到我启动命令的根目录。由于这些压缩文件中有 none 个在我的控制之下(我没有创建它们),所以它们在归档时没有保留原始目录结构。所以我被迫找到一个为什么要在解压缩它们之前'cd'将目录更改为它们所在的子目录。
这是我现在要做的事情...
$ find . -type f -name "*.zip" -exec 7z x -r -spe -tzip '{}' \;
$ find . -type f -name "*.7z" -exec 7z x -r -spe '{}' \;
如果找到压缩文件并在该位置解压缩,我该如何着手'cd'?我想象添加检查和命令需要某种 'while' 循环。
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
命令提取文件名本身。
为了确保这是安全的并且可以处理其中包含空格的文件名,我们打印以 null 结尾的字符串(-print0
加上 xargs -0
)而不是使用 -exec
。 xargs
将获取 stdin
中的所有行并调用给定的命令行,此处调用 bash
对目录执行 cd
,然后对文件名本身执行取消归档命令.
如果您没有安装 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
reads(@
,由 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
我有几个压缩文件,它们的子目录中有 embedded/nested 个压缩文件,使用各种压缩格式,例如7z,邮编,tar。如果我使用以下方法(见下文)递归解压缩它们,所有文件都将解压缩到我启动命令的根目录。由于这些压缩文件中有 none 个在我的控制之下(我没有创建它们),所以它们在归档时没有保留原始目录结构。所以我被迫找到一个为什么要在解压缩它们之前'cd'将目录更改为它们所在的子目录。
这是我现在要做的事情...
$ find . -type f -name "*.zip" -exec 7z x -r -spe -tzip '{}' \;
$ find . -type f -name "*.7z" -exec 7z x -r -spe '{}' \;
如果找到压缩文件并在该位置解压缩,我该如何着手'cd'?我想象添加检查和命令需要某种 'while' 循环。
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
命令提取文件名本身。
为了确保这是安全的并且可以处理其中包含空格的文件名,我们打印以 null 结尾的字符串(-print0
加上 xargs -0
)而不是使用 -exec
。 xargs
将获取 stdin
中的所有行并调用给定的命令行,此处调用 bash
对目录执行 cd
,然后对文件名本身执行取消归档命令.
如果您没有安装 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
reads(@
,由 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