Làm thế nào để giải nén, giải nén -xvf - hủy lưu trữ trong một thư mục lộn xộn?


14

Thông thường, tôi không lưu trữ mọi thứ bằng cách $ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zipnhưng đôi khi tôi trở nên lười biếng và chỉ làm trong một thư mục tùy ý $ unzip *.zipđể thỉnh thoảng làm rối tung nội dung khác. Tôi sẽ liệt kê ở đây một số phương pháp - một số phiên bản lưu trữ chắc chắn có cờ crappy trong khi các phương pháp khác có nhiều spartan hơn, tôi quan tâm đến cái sau hơn.

Một số cách để hủy đăng ký, có những cách khác?

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;Điểm yếu là nó liệt kê các thư mục *.zip, vì vậy bạn cần sử dụng chậm -ok, chậm với nhiều *.ziptrận đấu và vì một lý do nào đó, nó dường như không khớp với mọi thứ được trích xuất.

  2. Nếu một lượng nhỏ các tệp được giải nén, từng cái một, chậm, cồng kềnh và dễ bị lỗi.

  3. Khi tôi muốn chắc chắn liệu nội dung của lưu trữ có thực sự là một thư mục hay không, đôi khi tôi kiểm tra nó $ unzip -l *.bsd, hoạt động ít nhất là trong phiên bản unzip của obsd.

Nếu bạn đang đề cập đến một số công cụ lưu trữ nhất định, xin vui lòng, nêu chúng khi thích hợp. Mặc dù vậy, hãy giữ cho nó đơn giản - Tôi quan tâm nhiều hơn đến CÁCH bạn làm điều đó hơn là một công cụ duy nhất.



Đây là một kịch bản tôi sử dụng để tự động hóa các mkdir; unzipcông cụ để tôi không bao giờ quá lười biếng để làm điều đó! svn.mikelward.com/svn/scripts/untar
Mikel

2
Xem câu hỏi và câu trả lời liên quan này: unix.stackexchange.com/questions/5123/ Kẻ
alex

Câu trả lời:


11

Bằng tên

Bạn có thể tạo danh sách các tệp trong kho lưu trữ và xóa chúng, mặc dù điều này gây khó chịu với các trình lưu trữ như giải nén hoặc 7z không có tùy chọn để tạo danh sách tên tệp đơn giản. Ngay cả với tar, điều này giả định không có dòng mới trong tên tệp.

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

Thay vì xóa các tệp, bạn có thể di chuyển chúng đến đích dự định của chúng.

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

Sử dụng cầu chì

Thay vì phụ thuộc vào các công cụ bên ngoài, bạn có thể (trên hầu hết các thông báo) sử dụng FUSE để thao tác lưu trữ bằng các lệnh hệ thống tập tin thông thường.

Bạn có thể sử dụng Fuse-zip để nhìn trộm vào zip, giải nén nó cp, liệt kê nội dung của nó với find, v.v.

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 tạo chế độ xem toàn bộ hệ thống phân cấp thư mục của bạn trong đó tất cả các tài liệu lưu trữ có một thư mục được liên kết (cùng tên với # được xử lý ở cuối) xuất hiện để giữ nội dung lưu trữ.

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

Theo ngày

Giả sử đó vẫn chưa được bất kỳ hoạt động khác trong hệ thống phân cấp cùng hơn khai thác, bạn có thể nói với các tập tin được trích xuất bởi gần đây của họ ctime . Nếu bạn vừa tạo hoặc di chuyển tệp zip, bạn có thể sử dụng nó làm điểm cắt; mặt khác sử dụng ls -lctrđể xác định thời gian cắt phù hợp. Nếu bạn muốn đảm bảo không xóa các khóa, không có lý do gì để thực hiện bất kỳ phê duyệt thủ công nào: findhoàn toàn có khả năng loại trừ chúng. Dưới đây là các lệnh ví dụ sử dụng zsh hoặc find; lưu ý rằng -cmin-cnewercác nguyên tắc không có trong POSIX mà tồn tại trên Linux (và các hệ thống khác có GNU find), * BSD và 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

Với GNU find, FreeBSD và OSX, một cách khác để chỉ định thời gian cắt là tạo một tệp và sử dụng touchđể đặt mtime của nó thành thời gian cắt.

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

Thay vì xóa các tệp, bạn có thể di chuyển chúng đến đích dự định của chúng. Đây là một cách với GNU / * BSD / OSX find, tạo các thư mục ở đích khi cần.

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

Tương đương Zsh (gần như: cái này tái tạo toàn bộ hệ thống phân cấp thư mục, không chỉ các thư mục sẽ chứa các tệp):

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

Cảnh báo, tôi đã không kiểm tra hầu hết các lệnh trong câu trả lời này. Luôn xem lại danh sách các tập tin trước khi gỡ bỏ (chạy echotrước, sau đó rmnếu nó ổn).


Cuối cùng tôi đã gặp vấn đề này ngày hôm nay. Là gốc! Cuối cùng, tôi đã sử dụng kết hợp "Theo tên" và "Theo ngày"
phunehehe

1

Tôi cảm thấy ngu ngốc, dù sao tôi cũng gãi đầu để viết kịch bản này khi tôi gặp vấn đề tương tự. Tôi đã sử dụng cpiovới -itcờ để có được một danh sách các tập tin; bạn có thể sử dụng các lệnh tương đương cho các trình lưu trữ khác. Phần khó khăn là, kho lưu trữ cpio là từ một initrd và tôi đã trích xuất vào /, vì vậy nhiều thư mục và tệp có cùng tên như trong một hệ thống làm việc. May mắn thay, cpio đã không ghi đè lên bất kỳ tập tin hiện có của tôi. Tôi sử dụng kiểm tra thời gian để đảm bảo không xóa bất cứ thứ gì tồn tại trước lệnh sai.

#! /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

Làm thế nào về việc cung cấp danh sách các tập tin trong kho lưu trữ xargs rm?

Đó sẽ là tar -tf tarbomb.tar | xargs rmhoặc unzip --list zipbomb.zip | xargs rm.


2
Các lệnh được đưa ra sẽ không hoạt động trong trường hợp chung và điều này rất nguy hiểm vì bạn đang xóa các tệp. xargsmong đợi đầu vào của nó được trích dẫn theo một cách đặc biệt mà findkhông sản xuất. Sử dụng xargs -I rm {}để xargs xử lý một mục trên mỗi dòng thay thế. Đối với lệnh giải nén, bạn có triển khai gì? Của tôi (Debian / Ubuntu) không có --list, chỉ -lvà nó không chỉ in tên tệp, do đó cần xử lý thêm.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles: 1) đúng, nó nguy hiểm, nhưng có lẽ chúng ta đã ghi đè lên các tệp gốc - chúng đã biến mất. 2) Tôi đã không nói về find. 3) bạn đã đúng unzip, tôi đã không kiểm tra và dường như không có tùy chọn nào cho danh sách chưa được yêu cầu. Không có --listtrên Ubuntu của tôi - tôi chỉ không thử nghiệm.
alex

Xin lỗi về phản ứng đóng hộp, thay thế tar -tcho find. Nhưng những điểm khác của tôi đứng. Có một rủi ro thực sự là lệnh của bạn được đưa ra sẽ xóa một tệp không liên quan.
Gilles 'SO- ngừng trở nên xấu xa'

tar -tf tarbomb.tarsẽ in tên tệp trên mỗi dòng, do đó bạn có thể làm tar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; donehoặc tương tự.
Mikel

0

Không thực sự những gì bạn yêu cầu nhưng làm thế nào để sử dụng một tập lệnh "giải nén tất cả" thay vì.

unzip *.zip

Bằng cách đó, đầu ra từ mỗi tệp đi vào thư mục riêng của nó.

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

0

Tôi sử dụng chức năng sau trong zsh:

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

Tức là thay thế lệnh để loại bỏ tất cả các tập tin trong đầu ra được làm sạch của unzip -l.

tar tvf có thể được sử dụng theo cách tương tự.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.