这就是我提取文件夹中所有文件的方式(递归):
find -iname \*.epub -exec unzip -o {} \;
但提取的文件最终全部位于父文件夹中:
Parent (Extracted Epub files)
Child (Epub files)
Child (Epub files)
如何更改该命令,以便将它们提取到自己的文件夹中?
Parent
Child (Epub files and extracted Epub files)
Child (Epub files and extracted Epub Files)
答案1
如果您使用 GNU find
,请使用其-execdir
操作:
find -iname \*.epub -execdir unzip -o {} \;
这将从找到文件的每个目录运行unzip
,确保将文件提取到适当的子目录中。
如果您指定起始目录,这至少也适用于某些 BSD(特别是 OpenBSD):
find /path/to/start -iname \*.epub -execdir unzip -o -- {} \;
答案2
斯蒂芬·基特的-execdir
回答很好,但如果多个文件可能.epub
位于同一目录中(所以-execdir
没有帮助),您需要执行以下操作:
find ./ -iname '*.epub' -exec sh -c '
for f; do
rp="$(realpath -e "$f")"
bn="$(basename "$f" .epub)"
dn="$(dirname "$rp")/$bn"
[ -e "$dn" ] && continue
echo mkdir -p "$dn"
echo unzip -d "$dn" -o "$rp"
done' find-sh {} +
"$f"
对于传递给 sh 脚本的每个参数 ( ),它用于realpath
将其完整绝对路径名获取到变量中rp
,basename
然后用于将不带 .epub 扩展名的基本文件名获取到变量中bn
。 dirname
用于获取绝对目录名称,并"/$bn"
附加给我们变量dn
。顺便说一句,所有这三个程序都在 GNU 中核心工具。
如果"$dn"
已经存在,则在语句中跳过它continue
(如果需要,这将是添加更多错误检查和错误处理代码的好地方)。否则,它是通过mkdir -p
unzip 选项创建并用作参数的-d
。 "$rp"
用作 的文件名 arg unzip
。
注意:这是作为试运行编写的,因此它只打印它所要的内容会做,但没有真正做。从命令中删除echo
语句以使其实际创建目录并将 .epub 文件提取到其中。
您可能需要添加echo "$rp"
orecho "$f"
语句并使用unzip
's-q
选项来减少输出的噪音量,同时在迭代文件名时仍显示进度。
答案3
使用 GNUsed
和find
支持现在常见(尽管不是标准)-iname
/-print0
谓词的实现,您可以执行以下操作:
LC_ALL=C find . -iname '?*.epub' \
! -name '*[[*?]*' \
! -iname ..epub \
! -iname ...epub \
-type f -print0 |
LC_ALL=C sed -z 'h;s/\.epub$//;p;g' |
xargs -r0n2 unzip -d
(跳过包含[
,*
或?
字符的文件名,以解决unzip
将它们视为通配符以查找匹配文件的错误功能)。
哪个会运行
unzip -d ./path/to/file ./path/to/file.epub
将文件内容解压epub
到以文件命名的目录中,不带扩展名。
我们还跳过.epub
(?*
之前需要至少一个字节.
)..epub
和...epub
文件,因为相应的目录将是""
,.
这..
将是一个问题。
或者使用 zsh:
set -o extendedglob
for f (./**/(^*[[*?]*).(#i)epub(N.)) unzip -d $f:r $f
./**/(^(|.|..|*[[?*]*)).(#i)epub(ND.)
这里省略隐藏的,如果需要的话将 glob 更改为(再次排除.epub
, ..epub
, ...epub
)。
有了,我们可以通过替换为, with ...来更好地解决, ,字符的zsh
问题。[
?
*
*
[*]
?
[?]
set -o extendedglob
for f (./**/*.(#i)epub(N.)) unzip -d $f:r $f:h/${${f:t}//(#m)[[?*]/[$MATCH]}
或者您可以使用更 Unixy 的命令来提取 zip 存档,例如 libarchive 的bsdtar
:
set -o extendedglob
for f (**/*.(#i)epub(N.)) {
mkdir -p -- $f:r && bsdtar -C $f:r -xf $f
}
或者,使用find
并包含隐藏的:
LC_ALL=C find . -iname '?*.epub' ! -iname ..epub ! -iname ...epub -exec sh -c '
for file do
dir=${file%.*}
mkdir -p "$dir" &&
bsdtar -C "$dir" -xf "$file"
done' sh {} +