วิธีการยกเลิกการซิป, de-tar -xvf - ยกเลิกการเก็บถาวรในโฟลเดอร์ยุ่ง?


14

โดยปกติแล้วฉันไม่ได้เก็บสิ่งต่าง ๆ ด้วย$ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zipแต่บางครั้งฉันก็ขี้เกียจและทำในโฟลเดอร์ตามอำเภอใจ$ unzip *.zipดังนั้นเวลาที่ทำกับเนื้อหาอื่น ฉันจะแสดงรายการวิธีการที่นี่ - บางรุ่นเก็บถาวรแน่นอนมีเส็งเคร็งธงในขณะที่คนอื่น ๆ สปาร์ตันมากขึ้นฉันสนใจมากขึ้นเกี่ยวกับหลัง

มีวิธีอื่นในการยกเลิกการเก็บถาวรหรือไม่

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;จุดอ่อนคือมันแสดงรายการ*.zipdirs ดังนั้นคุณจำเป็นต้องใช้ช้า-okช้ากับการ*.zipแข่งขันจำนวนมากและด้วยเหตุผลบางอย่างดูเหมือนจะไม่ตรงกับทุกสิ่งที่สกัด

  2. หากไฟล์ที่ได้รับการขยายออกมาจำนวนเล็กน้อยไฟล์แบบหนึ่งต่อหนึ่งช้าช้าและมีข้อผิดพลาดเกิดขึ้นได้ง่าย

  3. เมื่อฉันต้องการตรวจสอบให้แน่ใจว่าเนื้อหาของ archieve นั้นเป็นโฟลเดอร์จริงหรือไม่บางครั้งฉันก็ตรวจสอบด้วย$ unzip -l *.bsdทำงานได้อย่างน้อยใน unzip-version ของ obsd

หากคุณอ้างถึงเครื่องมือเก็บถาวรบางอย่างโปรดระบุสิ่งเหล่านี้ตามความเหมาะสม ทำให้มันง่ายขึ้น - ฉันสนใจวิธีการของคุณมากกว่าที่จะเป็นเครื่องมือเดียว



นี่คือสคริปต์ที่ฉันใช้เพื่อทำให้mkdir; unzipสิ่งต่าง ๆเป็นแบบอัตโนมัติดังนั้นฉันจึงไม่เคยขี้เกียจทำมัน! svn.mikelward.com/svn/scripts/untar
Mikel

2
ดูคำถามและคำตอบที่เกี่ยวข้องนี้: unix.stackexchange.com/questions/5123/…
alex

คำตอบ:


11

โดยชื่อ

คุณสามารถสร้างรายชื่อไฟล์ในไฟล์เก็บถาวรและลบไฟล์ได้แม้ว่าจะเป็นไฟล์ที่มีปัญหากับไฟล์เก็บถาวรเช่น unzip หรือ 7z ซึ่งไม่มีตัวเลือกในการสร้างรายชื่อไฟล์ธรรมดา แม้ว่าจะมี tar แต่ก็ถือว่าไม่มีบรรทัดใหม่ในชื่อไฟล์

tar tf foo.tar | while read -r file; do rm -- "$file" done
unzip -l foo.zip | awk '
    p && /^ --/ {p=2}
    p==1 {print substr($0, 29)}
    /^ --/ {++p}
' | while …
unzip -l foo.zip | tail -n +4 | head -n -2 | while …  # GNU coreutils only
7z l -slt foo.zip | sed -n 's/^Path = //p' | while …  # works on tar.*, zip, 7z and more

แทนที่จะลบไฟล์คุณสามารถย้ายไฟล์ไปยังปลายทางที่ต้องการได้

tar tf foo.tar | while read -r file; do
  if [ -d "$file" ]; then continue; fi
  mkdir -p "/intended/destination/${file%/*}"
  mv -- "$file" "/intended/destination/$file"
done

ใช้ FUSE

แทนที่จะขึ้นอยู่กับเครื่องมือภายนอกคุณสามารถ (โดยส่วนใหญ่) ใช้FUSEเพื่อจัดการกับไฟล์เก็บถาวรโดยใช้คำสั่งระบบไฟล์ธรรมดา

คุณสามารถใช้Fuse-zipเพื่อมองเข้าไปในซิปแยกมันcpออกแสดงรายการเนื้อหาด้วยfindฯลฯ

mkdir /tmp/foo.d
fuse-zip foo.zip /tmp/foo.d
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd /tmp/foo.d && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm /tmp/foo.d/**(:"s~/tmp/foo.d/~~"^/)
## Extract the contents where you really want them
cp -Rp /tmp/foo.d /intended/destination
fusermount -u foo.d
rmdir foo.d

AVFSสร้างมุมมองของลำดับชั้นไดเรกทอรีทั้งหมดของคุณที่เก็บถาวรทั้งหมดมีไดเรกทอรีที่เกี่ยวข้อง (ชื่อเดียวกันกับ # tacked ในตอนท้าย) ที่ปรากฏขึ้นเพื่อเก็บเนื้อหาที่เก็บถาวร

mountavfs
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd ~/.avfs/"$PWD/foo.zip#" && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm ~/.avfs/$PWD/foo.zip\#/**/*(:"s~$HOME/.avfs/$PWD/foo.zip#~~"^/)
## Extract the contents where you really want them
cp -Rp ~/.avfs/"$PWD/foo.zip#" /intended/destination
umountavfs

ตามวันที่

สมมติว่ามีไม่ได้ดำเนินการใด ๆ อื่น ๆ ในลำดับชั้นเดียวกันกว่าการสกัดของคุณคุณสามารถบอกได้ว่าไฟล์ที่สกัดโดยล่าสุดของพวกเขาctime หากคุณเพิ่งสร้างหรือย้ายไฟล์ zip คุณสามารถใช้มันเป็นทางลัดได้ มิฉะนั้นใช้ls -lctrเพื่อกำหนดเวลาตัดยอดที่เหมาะสม หากคุณต้องการให้แน่ใจว่าจะไม่ลบรหัสไปรษณีย์ไม่มีเหตุผลใดที่จะต้องทำการอนุมัติด้วยตนเอง: findสามารถแยกออกได้อย่างสมบูรณ์แบบ นี่คือตัวอย่างคำสั่งที่ใช้ zsh หรือfind; โปรดทราบว่า-cminและอุปกรณ์-cnewerไม่ได้อยู่ใน POSIX แต่มีอยู่บน Linux (และระบบอื่น ๆ ที่มี GNU find), * BSD และ OSX

find . \! -name '*.zip' -type f -cmin -5 -exec rm {} +  # extracted <5 min ago
rm **/*~*.zip(.cm-6)  # zsh, extracted ≤5 min ago
find . -type f -cnewer foo.zip -exec rm {} +  # created or moved after foo.zip

ด้วย GNU find, FreeBSD และ OSX, อีกวิธีหนึ่งในการระบุเวลาในการตัดคือการสร้างไฟล์และใช้touchเพื่อตั้งค่า mtime ให้เป็นเวลาตัด

touch -d … cutoff
find . -type f -newercm cutoff -delete

แทนที่จะลบไฟล์คุณสามารถย้ายไฟล์ไปยังปลายทางที่ต้องการได้ นี่คือวิธีที่มี GNU / * BSD / OSX ค้นหาสร้างไดเรกทอรีในปลายทางตามต้องการ

find . \! -name . -cmin -5 -type f -exec sh -c '
    for x; do
      mkdir -p "$0/${x%/*}"
      mv "$x" "$0/$x"
    done
  ' /intended/destination {} +

Zsh เทียบเท่า (เกือบ: อันนี้จะทำซ้ำลำดับชั้นไดเรกทอรีทั้งหมดไม่เพียง แต่ไดเรกทอรีที่จะมีไฟล์):

autoload zmv
mkdir -p ./**/*(/cm-3:s"|.|/intended/destination|")
zmv -Q '(**/)(*)(.cm-3)' /intended/destination/'$1$2'

คำเตือนฉันยังไม่ได้ทดสอบคำสั่งส่วนใหญ่ในคำตอบนี้ ตรวจสอบรายชื่อไฟล์ทุกครั้งก่อนที่จะทำการลบ (เรียกใช้echoก่อนจากนั้นrmถ้าตกลง)


ในที่สุดฉันก็พบปัญหานี้ในวันนี้ ในฐานะที่เป็นราก! ในท้ายที่สุดผมใช้การรวมกันของ "โดยชื่อ" และ "โดยวันที่"
phunehehe

1

ฉันรู้สึกงี่เง่าแล้วฉันเกาหัวของฉันเพื่อเขียนสคริปต์นี้เมื่อฉันมีปัญหาที่คล้ายกัน ฉันใช้cpioกับ-itแฟล็กเพื่อรับรายการไฟล์ คุณสามารถใช้คำสั่งที่เทียบเท่าสำหรับผู้จัดเก็บอื่น ๆ ส่วนที่ยุ่งยากคือไฟล์เก็บถาวร cpio นั้นมาจาก initrd และฉันแยกไฟล์ออกมา/ดังนั้นโฟลเดอร์และไฟล์จำนวนมากจึงมีชื่อเหมือนกับในระบบการทำงาน โชคดีที่ cpio ไม่ได้เขียนทับไฟล์ที่มีอยู่ของฉัน ฉันใช้การตรวจสอบเวลาเพื่อให้แน่ใจว่าจะไม่ลบสิ่งที่มีอยู่ก่อนคำสั่งที่ผิด

#! /bin/sh

files=$(cpio -it < /mnt/temp/lglive.cpio)

for i in ${files}
do
    name=$(stat -c "%n" ${i})
    time=$(stat -c "%Y" ${i})
    # Time of the creation of the mess: 1296457595
    if [[ ${time} -gt 1296457590 && ${time} -lt 1296457600 ]]
    then
        if [[ -f ${name} ]]
        # If it is a file, it must have been created as part of the mess.
        then
            echo "rm ${name}"
        elif [[ -d ${name} ]]
        # If it is a directory, it may have been part of the mess
        # or maybe some files underneath it is created as part of the mess.
        then
            if [[ $(ls -A ${name}) ]]
            # If the directory contains something then don't delete it.
            then
                echo "${name} is not empty"
            # If the directory is empty then assume it is rubbish.
            else
                echo "rmdir ${name}"
            fi
        fi
    fi
done

echo "Files and directories still exist after the removal:"
for i in ${files}
do
    if [[ -e ${i} ]]
    then
        echo ${i}
    fi
done

0

วิธีการเกี่ยวกับรายการของไฟล์ในเก็บถาวรเพื่อxargs rm?

ที่จะเป็นหรือtar -tf tarbomb.tar | xargs rmunzip --list zipbomb.zip | xargs rm


2
คำสั่งที่ให้มาจะไม่ทำงานในกรณีทั่วไปและเป็นอันตรายเนื่องจากคุณลบไฟล์ xargsคาดว่าการป้อนข้อมูลของมันจะยกมาในรูปแบบแปลกประหลาดที่findไม่ได้ผลิต ใช้xargs -I rm {}เพื่อให้ xargs ประมวลผลหนึ่งรายการต่อบรรทัดแทน สำหรับคำสั่ง unzip คุณมีการนำไปใช้งานอะไรบ้าง Mine (Debian / Ubuntu) ไม่มี--listเฉพาะ-lและไม่เพียงพิมพ์ชื่อไฟล์ดังนั้นจำเป็นต้องมีการประมวลผลเพิ่มเติม
Gilles 'หยุดความชั่วร้าย'

@Gilles: 1) ใช่มันเป็นอันตราย แต่เนื่องจากเราได้เขียนทับไฟล์ต้นฉบับ - พวกเขาหายไปแล้ว 2) findฉันไม่ได้พูดคุยเกี่ยวกับ 3) คุณถูกต้องunzipฉันไม่ได้ทดสอบและดูเหมือนจะไม่มีตัวเลือกสำหรับรายชื่อที่ไม่ได้รับการตกแต่ง ไม่--listบน Ubuntu ของฉันด้วย - ฉันไม่ได้ทดสอบ
alex

ขออภัยเกี่ยวกับการตอบสนองกระป๋องทดแทนสำหรับtar -t findแต่จุดอื่น ๆ ของฉันยืน มีความเสี่ยงจริงที่คำสั่งของคุณตามที่กำหนดจะลบไฟล์ที่ไม่เกี่ยวข้อง
Gilles 'หยุดชั่วร้าย'

tar -tf tarbomb.tarจะพิมพ์ชื่อไฟล์หนึ่งชื่อต่อบรรทัดดังนั้นคุณสามารถทำได้tar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; doneหรือคล้ายกัน
มิเคล

0

ไม่ใช่สิ่งที่คุณขอจริงๆ แต่จะใช้สคริปต์ "unzip all" แทน

unzip *.zip

วิธีที่เอาต์พุตจากแต่ละไฟล์ไปยังไดเร็กทอรีของตัวเอง

#!/bin/bash
for f in *.zip ; do unzip -n "$f" -d "${f/%zip/out}"; done

0

ฉันใช้ฟังก์ชั่นต่อไปนี้ใน zsh:

ununzip () {
    rm -r $(unzip -l $1 | grep -v 'Archive:' | \
    grep '[/.]' | sed 's![^a-zA-Z]([a-zA-Z./])!\1!')
}

คือการทดแทนคำสั่ง Ie เพื่อลบไฟล์ทั้งหมดในเอาต์พุตที่ล้างข้อมูลunzip -lแล้ว

tar tvf สามารถใช้ในทำนองเดียวกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.