जैसा कि माथियास ने कहा, unzipइस तरह का कोई विकल्प नहीं है, लेकिन एक-लाइनर बैश स्क्रिप्ट काम कर सकती है।
समस्या यह है: सबसे अच्छा तरीका आपके आर्काइव लेआउट पर निर्भर करता है। एक समाधान जो एक शीर्ष स्तर के डीआईआर को मानता है, अगर सामग्री सीधे आर्क रूट में होती है (विचार करें /a/foo /b/foo /fooऔर स्ट्रिपिंग की अराजकता के बारे में ) /aऔर /b।
और वही असफलता होती है tar --strip-component। कोई एक आकार-फिट-सभी समाधान नहीं है।
तो, जड़ dir पट्टी, यह मानते हुए वहाँ है एक (और केवल एक):
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
बस यह सुनिश्चित करें कि दूसरे स्तर की फाइलें / dirs में शीर्ष-स्तरीय माता-पिता (उदाहरण के लिए ) का समान नाम नहीं है /foo/foo। लेकिन /foo/bar/fooऔर /foo/bar/barठीक हैं। यदि वे करते हैं, या आप सुरक्षित रहना चाहते हैं, तो आप निष्कर्षण के लिए एक अस्थायी डीआईआर का उपयोग कर सकते हैं:
temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"
यदि आप बैश का उपयोग कर रहे हैं, तो आप परीक्षण कर सकते हैं कि शीर्ष स्तर एकल डायर है या उपयोग नहीं कर रहा है:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
बैश की बात करते हुए, आपको dotglobछिपी हुई फ़ाइलों को शामिल करने के लिए चालू करना चाहिए , और आप एक ही, आसान कार्य में सब कुछ लपेट सकते हैं:
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"
)
अब इसे अपने ~/.bashrcया ~/.profileआप के बारे में चिंता करने की ज़रूरत नहीं है। बस के रूप में उपयोग करें:
unzip-strip sourcefile.zip mysubfolder
( mysubfolderयदि यह मौजूद नहीं है तो यह आपके लिए स्वतः ही सूचना देगा )