Tương đương với tar's-tar --strip-thành phần = 1 bản in giải nén?


49

Tôi có một tập lệnh trích xuất tệp tar.gz sang thư mục con được chỉ định mysubfolder :

mkdir mysubfolder; tar --extract --file=sourcefile.tar.gz --strip-components=1 --directory=mysubfolder;

Có cách nào tương đương để làm điều này với một tệp zip không?


2
Chỉ cần sử dụng bsdtar
Drizzt

Câu trả lời:


26

Như Mathias đã nói, unzipkhông có tùy chọn như vậy, nhưng một tập lệnh bash một lớp có thể thực hiện công việc.

Vấn đề là: cách tiếp cận tốt nhất phụ thuộc vào bố cục lưu trữ của bạn. Một giải pháp giả định một thư mục cấp cao nhất sẽ thất bại thảm hại nếu nội dung trực tiếp trong thư mục gốc lưu trữ (suy nghĩ /a/foo /b/foo /foovà sự hỗn loạn của tước /a/b).

Và thất bại tương tự xảy ra với tar --strip-component. Không có giải pháp một kích cỡ phù hợp cho tất cả.

Vì vậy, để tước dir gốc, giả sử có một (và chỉ một):

unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"

Chỉ cần đảm bảo các tệp / thư mục cấp hai không có cùng tên của cha mẹ cấp cao nhất (ví dụ /foo/foo:). Nhưng /foo/bar/foo/foo/bar/barđều ổn. Nếu họ làm như vậy, hoặc bạn chỉ muốn an toàn, bạn có thể sử dụng thư mục tạm thời để trích xuất:

temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"

Nếu bạn đang sử dụng Bash, bạn có thể kiểm tra xem cấp cao nhất có phải là một thư mục đơn hay không sử dụng:

f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"

Nói về Bash, bạn nên bật dotglobđể bao gồm các tệp ẩn và bạn có thể gói mọi thứ trong một chức năng duy nhất, tiện dụng:

unzip-strip() (
    local zip=$1
    local dest=${2:-.}
    local temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
    shopt -s dotglob && local f=("$temp"/*) &&
    if (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] ; then
        mv "$temp"/*/* "$dest"
    else
        mv "$temp"/* "$dest"
    fi && rmdir "$temp"/* "$temp"
)

Bây giờ hãy đặt nó trong ~/.bashrchoặc hoặc ~/.profilebạn sẽ không bao giờ phải lo lắng về điều đó nữa. Đơn giản chỉ cần sử dụng như:

unzip-strip sourcefile.zip mysubfolder

(chú ý nó sẽ tự động tạo mysubfoldercho bạn nếu nó không tồn tại)


Điều này sẽ không giải nén vào cấu trúc thư mục hiện có như tôi mong muốn (tôi đã thử sử dụng. Thay cho mysubfolder). Cuối cùng tôi chỉ giải nén (giải nén zip-with-top-dir.zip) và sau đó sao chép (cp -rv extract-top-zip-dir / *.).
catgofire

4

Tôi không thể tìm thấy một tùy chọn như vậy trong các trang hướng dẫnunzip , vì vậy tôi sợ điều này là không thể. :

Tuy nhiên, (tùy thuộc vào tình huống) bạn có thể làm việc xung quanh nó. Ví dụ: nếu bạn chắc chắn thư mục cấp cao nhất trong tệp zip được đặt tên foo-theo sau là số phiên bản, bạn có thể làm một cái gì đó như thế này:

cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder

Cách tiếp cận đẹp, nhưng hơi không đầy đủ: bạn vẫn sẽ có foo * dir với nội dung được trích xuất đầy đủ.
MestreLion

Có, tôi đã không thêm rm -rf foo-*vào mục đích vì điều đó có khả năng nguy hiểm. Điều gì nếu đã có một thư mục có tên foo-bar? Lưu ý rằng việc trích xuất đang được thực hiện trong /tmpthư mục, việc này sẽ tự động được làm trống.
Mathias Bynens

Đó là lý do tại sao tôi xâu chuỗi các thao tác bằng cách sử dụng &&: một bước nhất định chỉ xảy ra nếu bước trước đó thành công, vì vậy bước cuối cùng ( rmchỉ) chỉ chạy nếu tất cả các bước hoàn thành không có lỗi.
MestreLion

2
Đó cũng là lý do tại sao một người không bao giờ nên sử dụng /tmp/some-hardcoded-folder-namenhư một thư mục tạm thời, mà thay vào đó nên sử dụng mktempcho điều đó: nó đảm bảo sẽ không có thư mục hiện có như vậy. Kiểm tra câu trả lời của tôi dưới đây.
MestreLion

1

Bạn có thể sử dụng -jđường dẫn rác (không tạo thư mục). Điều này chỉ được khuyến nghị cho các tài liệu lưu trữ một cấp phổ biến. Lưu trữ với cấu trúc thư mục đa cấp sẽ được làm phẳng - điều này thậm chí có thể dẫn đến xung đột tên cho các tệp để giải nén.

Từ trang man của giải nén:

   -j     junk  paths.   The  archive's directory structure is not recreated; all files are deposited in the
          extraction directory (by default, the current one).
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.