bash (unix shell scripting) 解压多个 zip 文件,按照 zip 文件名重命名解压后的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25432321/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:12:08  来源:igfitidea点击:

(unix shell scripting) Unzip multiple zip files, rename unzipped file following zip file name

bashshellunixzipunzip

提问by Thuan Nguyen

I have multiple zip files like this example:

我有多个 zip 文件,如下例所示:

759198298412.zip
----i love you.pdf
----forever and one.txt
----today and tomorrow.docs
48891721241592__5123.zip
----whatever it is.pdf
5717273_616.zip
----igotit.txt
----thank you very much.mp3    

I am trying to make a script to unzip the zip files, and rename the unzipped files to the zip file name. like this output:

我正在尝试制作一个脚本来解压缩 zip 文件,并将解压缩的文件重命名为 zip 文件名。像这样的输出:

759198298412.pdf
759198298412.txt
759198298412.docs

48891721241592__5123.pdf

5717273_616.txt
5717273_616mp3

I found this script below, but it doesn't work for me because my files have space and i have multiple files in a zip file.

我在下面找到了这个脚本,但它对我不起作用,因为我的文件有空间并且我在一个 zip 文件中有多个文件。

for i in *.zip
do 
n=$(unzip -lqq $i | awk '{print $NF}')
e=${n#*.}
unzip $i && mv $n ${i%%_*}".$e"
done    

Please help! thank you

请帮忙!谢谢你

回答by Etan Reisner

for i in *.zip; do
    mkdir "$i-dir"
    cd "$i-dir"
    unzip "../$i"
    for j in *; do
        mv "$j" "$i.${j##*.}"
    done
    cd ..
done

If dropping everything after the first underscore in the file name is important than the mv line should be:

如果删除文件名中第一个下划线之后的所有内容很重要,那么 mv 行应该是:

mv "$j" "${i%%_*}.${j##*.}"

And to have that dropping work even when no underscore is present in the zip file name use:

并且即使在 zip 文件名中不存在下划线的情况下也要进行删除工作,请使用:

i=${i%.zip}; mv "$j" "${i%%_*}.${j##*.}"

And to keep the files all in the top-level directory prefix ../to the mvtarget filename.

并将文件全部保留../mv目标文件名的顶级目录前缀中。

回答by Beggarman

A few small changes:

一些小的变化:

  1. Quote variables to deal with the spaces in file names.
  2. Use unzip -Z -1to get a listing of the files in the archive to avoid using awk (which is printing just the final part of names with spaces).
  3. Since unzip -Z -1splits records by line, we set the IFS to '\n' so records split properly.
  4. Replace the underscore in the move to a dot so .zip extension is removed.
  1. 引用变量来处理文件名中的空格。
  2. 使用unzip -Z -1来获取文件的列表中存档,以避免使用AWK(这是打印的名字与空间只有最后一部分)。
  3. 由于unzip -Z -1按行拆分记录,我们将 IFS 设置为 '\n' 以便记录正确拆分。
  4. 将移动中的下划线替换为点,以便删除 .zip 扩展名。

New script is:

新脚本是:

IFS=$'\n'
for i in *.zip
do
   for n in $(unzip -Z -1 "$i"); do 
       echo "$i - $n"
       e=${n#*.}
       unzip "$i" "$n" && mv "$n" ${i%%.*}".$e"
   done
done

Note that this script assumes you've only got one of each file extension in your zip. If that's not true, you'll need to handle duplicate files in some fashion.

请注意,此脚本假定您的 zip 文件中只有每个文件扩展名之一。如果不是这样,您将需要以某种方式处理重复文件。

Output after running:

运行后输出:

48891721241592__5123.pdf  
48891721241592__5123.zip  
759198298412.docs  
759198298412.pdf  
759198298412.txt  
759198298412.zip

回答by scht_r

for zip in *.zip; do
    zip_filename="${zip%%.*}"
    unzip "${zip}" -d "${zip_filename}-dir"

    for file in "${zip_filename}-dir"/*.*; do
        extension="${file##*.}"         
        new_name="${zip_filename}.${extension}"
        mv "${file}" "${new_name}"
    done

    rmdir "${zip_filename}-dir"
    # delete the zip file
    # rm "${zip}"
done

The script basically just unzips the files to a new temporary directory, it then renames all the files in the new directory and moves them out of the directory, and finally it deletes the temporary directory.

该脚本基本上只是将文件解压缩到一个新的临时目录,然后重命名新目录中的所有文件并将它们移出目录,最后删除临时目录。