giải nén tập tin, thư mục nào đã được tạo?


7

Mục tiêu:

Sau khi mở rộng lưu trữ a.zipbằng cách sử dụng lệnh unziptrên Ubuntu 12.10, gán tên của thư mục được a.zipmở rộng cho bashbiến v.

a.zip được giả định và đảm bảo mở rộng sang một thư mục, thay vì nhiều thư mục.

Thí dụ:

Nếu unzip a.zipmở rộng vào thư mục ./foo/, echo $vnên trả lại foo.

Môi trường của tôi:

GNU/Linux (kernel 3.5.0-25-generic)
Ubuntu 12.10    
bash v4.2.37(1)-release
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.

Cách giải quyết hiện tại tôi không hài lòng với: mở rộng thông qua unzip -d bar a.zipsau đó v=$(ls -1 bar)cho kết quả đúng, nhưng làm rối hệ thống tập tin.

Câu trả lời:


4

Ở đây bạn đi:

v=$(unzip a.zip | grep -m1 'creating:' | cut -d' ' -f5-)

Giải trình

  • $(...)là một vỏ chụp. Nó nắm bắt đầu ra của các lệnh bên trong nó và thay thế chúng như một biến.
  • Đầu ra của unziplệnh được dẫn tới grep, được truyền vào đối số -m1để làm cho nó chỉ trả về kết quả đầu tiên và văn bản creating:, là một phần của văn bản unzipin ra thiết bị xuất chuẩn khi nó tạo một thư mục. grepin creating: foo/ra thiết bị xuất chuẩn, được đường ống cut.
  • cutđược sử dụng để in tất cả các cột (cách nhau bởi khoảng trắng) sau cột thứ hai. Chúng tôi chỉ định từ 5 cho đến hết dòng mặc dù vì từ creating:này có tiền tố với một vài khoảng trắng. Chúng tôi muốn sử dụng tất cả các cột cho đến cuối dòng trong trường hợp tên thư mục có khoảng trắng trong đó. Đầu ra cuối cùng là foo/.

Cảm ơn! :) Tôi thích cách -m1bật grepvà tôi không biết về việc cutin đến cuối thông qua -fN-(bỏ qua số trường cuối cùng). Bạn đã dạy tôi một cái gì đó! Đối với điều này -> upvote! Bạn đã không sử dụng chỉ một công cụ (ví dụ awk) bởi vì 1. grepcutphổ biến rộng rãi hơn awkvà 2. bạn có thấy những gì bạn đã viết "dễ đọc" hơn không? Tôi muốn nghe lý do của bạn, vì người ta có thể pha chế một lớp lót, như vậy: stackoverflow.com/questions/15776352 PS: bạn không cần dấu ngoặc kép, không chia tách từ bash trong thời gian gán biến. v=$(echo a b)giống nhưv="$(echo a b)"
Robottinosino

Việc chọn tất cả các trường cho đến cuối dòng sẽ dễ dàng cuthơn so với khi kết thúc awk. Theo ý kiến ​​của tôi, nó cũng dễ đọc hơn một chút. Đó là một lót là thú vị. Tôi sẽ phải đọc thêm về awk. Sử dụng dấu ngoặc kép trong các bài tập biến là một thói quen xấu của tôi xuất phát từ trình soạn thảo văn bản tô màu văn bản bên trong dấu ngoặc kép. Ngoài ra, ngôn ngữ mặc định của tôi là C.

1
Đây là một mẹo thực sự tốt nhưng có vẻ như nhận được thư mục đầu ra theo cách này phá vỡ quá trình giải nén bằng cách nào đó. Có cách nào để có được dir đầu ra mà không phá vỡ quá trình giải nén?
Marcin Bobowski

2
  • Bạn có thể sử dụng unzip -lđể liệt kê nội dung của kho lưu trữ và phân tích đầu ra
  • Hoặc bạn có thể liệt kê thư mục, trích xuất arcive liệt kê lại thư mục đó và so sánh hai danh sách bằng cách sử dụng diff

Giải pháp của Evan trực tiếp hơn: trích xuất phân tích tên dir .. (mặc dù ý tưởng của bạn là tốt và là cơ sở cho giải pháp của Evan .. cho điều này - Tôi đang nâng cao lời cảm ơn ..)
Robottinosino

1

Hệ thống tệp AVFS trình bày một khung nhìn của hệ thống tệp trong đó mọi tệp lưu trữ /path/to/foo.zipcó thể truy cập dưới dạng một thư mục ~/.avfs/path/to/foo.zip#.

mountavfs
ls ~/.avfs$PWD/foo.zip\#

Nếu lslệnh đó hiển thị một thư mục duy nhất, thì việc giải nén tệp zip sẽ tạo thư mục đó và tạo các tệp bên dưới nó. Xin lưu ý rằng một tệp zip có thể hoặc không thể được tổ chức theo cách này.

Đây là một đoạn kiểm tra giả định của bạn và đặt dirthành tên thư mục nếu có. Cảnh báo: nếu tệp zip chứa các tệp có tên bắt đầu bằng .(tệp chấm), chúng sẽ bị bỏ qua.

zip_directory_name () {
  case $1 in
    /*) ;;
    *) set "$PWD/$1";;
  esac
  cd ~/.avfs${1}\# || exit 2
  set -- *
  if [ $# -eq 1 ] && [ -d "$1" ]; then
    printf %s "$1"
  else
    return 1 # more than one top-level file, or a single non-directory
  fi
}
dir=$(zip_directory_name foo.zip) || exit $?

1

Không hài lòng với cách giải quyết của bạn nếu bạn thích, nhưng thực sự đó là giải pháp chính xác.

d="`mktemp -d`"
unzip -d "$d" "$zipfile"
v="`basename "$d"/*`"
mv "$d"/"$v" "$v"
rmdir "$d"
echo "$v"

Đây là dài dòng, nhưng - miễn là thực sự chỉ có một thư mục trong zipfile, mà bạn có lẽ nên kiểm tra trước - nó đáng tin cậy.

lsgrepít đáng tin cậy hơn bởi vì nó phụ thuộc vào đầu ra trông như thế nào. Ở một miền khác, có thể không có chuỗi "tạo:" nào. Trong phiên bản tiếp theo của giải nén, nó có thể được thay đổi vì bất kỳ lý do gì.

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.