फ़ाइल निकालें, लेकिन केवल अगर यह एक सिमलिंक है


11

आदर्श रूप में मैं इस तरह की एक कमान चाहता हूं

rm --only-if-symlink link-to-file

क्योंकि मैंने अपने आप को कई बार गलती से फ़ाइल को इंगित करने वाले सिमलिंक के बजाय फ़ाइल को हटा दिया है। यह विशेष रूप से बुरा हो सकता है जब सूडो शामिल हो। अब मैं ls -alनिश्चित रूप से यह सुनिश्चित करने के लिए एक काम करता हूं कि यह वास्तव में एक सिम्लिंक है और ऐसा है लेकिन यह ऑपरेटर त्रुटि (इसी तरह की फ़ाइल, टाइपो, आदि) और दौड़ की स्थिति के लिए असुरक्षित है (यदि कोई मुझे किसी कारण से फ़ाइल को हटाना चाहता था)। क्या यह जांचने का कोई तरीका है कि क्या कोई फ़ाइल सिम्क्लिन है और केवल एक कमांड में होने पर उसे हटा दें?


1
मुझे नहीं लगता कि दौड़ की स्थिति एक चिंता का विषय होना चाहिए। जो कोई भी सिमलिंक को हटाने और एक फ़ाइल के साथ बदलने में सक्षम होगा, उसे निर्देशिका पर लिखने की अनुमति की आवश्यकता होगी, जिसका अर्थ है कि वे फ़ाइल को स्वयं भी हटा सकते हैं।
नैट एल्ड्रेडगे

जवाबों:


19
 $ rm_if_link(){ [ ! -L "$1" ] || rm -v "$1"; }

 #test
 $ touch nonlink; ln -s link
 $ rm_if_link nonlink
 $ rm_if_link link
   removed 'link'     

4
निश्चित रूप से इसे हटाने !और बदलने के ||लिए अधिक स्पष्ट होगा&&
ग्लेन जैकमैन

5
@glennjackman मैंने ||फॉर्म को पसंद करने की आदत बना ली है। &&यदि आप set -eमोड में हैं तो चीजों को नीचे लाते हैं ।
पीस्कोकिक

@PSkocik सामान्य रूप से जोखिम भरा है क्योंकि यह दिलचस्प मामले (फ़ाइल मौजूद है और एक सिमलिंक है) के बीच अंतर नहीं करता है और एक गैर-शून्य निकास कोड के लिए अन्य कारण, जैसे कि एक खाली अनारक्षित मूल्य ( [ ! -L $1 ]), एक अमान्य ऑपरेटर () का उपयोग करके [ ! -l foo ]), या यहां तक ​​कि वाक्यविन्यास त्रुटि ( [ ! -q foo || echo foo)
l0b0

2
@XiongChiamiov इसके साथ समस्या rm_if_link(){ [ -L "$1" ] && rm -v "$1"; }यह है कि इसे set -e मोड में नॉनलिंक पर चलाने से आपकी शेल प्रक्रिया समाप्त हो जाएगी। आप संलग्न कर सकते हैं || :लेकिन फिर यह ! ||संस्करण की तुलना में कम स्पष्ट, IMHO हो जाता है, और यह आपको rmविफलता को मारने से रोक देगा set -e, जो कि अवांछनीय है। ! ||काफी संक्षिप्त और स्पष्ट है, और इनमें से किसी भी समस्या से ग्रस्त नहीं है।
PSkocik

1
नहीं । अन्य विकल्प: ए) rmआपके परीक्षण के अंदर डालते हैं , बी) एक वास्तविक का उपयोग करते हैं यदि कथन, ग) -eइंटरैक्टिव गोले के अंदर का उपयोग न करें (और अपनी स्क्रिप्ट का परीक्षण करें!)। यदि आप पठनीयता के बारे में बहस करना चाहते हैं, ifतो परीक्षण के लिए यदि कोई लिंक है तो बहुत स्पष्ट रूप से विजेता है।
मोनिका सेलियो

5

आप उपयोग कर सकते हैं findऔर इसकी -type lपरीक्षण स्थिति (यह देखने के लिए परीक्षण करते हैं कि वस्तु एल स्याही है या नहीं)

उदाहरण के लिए, यदि आपके पास fooवर्तमान निर्देशिका में एक फ़ाइल है, तो आप ऐसा कर सकते हैं:

$ find . -type l -iname "foo" -delete

आप इसे सरल बनाने में सक्षम हो सकते हैं:

$ find . -maxdepth 1 -type l -delete

जो वर्तमान निर्देशिका में सभी सीमलिंक को हटा देगा।

चेतावनी:

में -deleteविकल्प findवास्तव में खतरनाक है। खोजे जाने के अंत में इसे स्थान पर रखें। यदि आप इसे गलत बताते हैं, तो यह सब कुछ इसे हटा देगा, चाहे परिणाम आपके सशर्त से मेल खाता हो।

जैसा कि टिप्पणियों में सुझाया गया है, एक सुरक्षित विकल्प का उपयोग किया जा सकता है findऔर rm -i(जो आपको फ़ाइल हटाने की पुष्टि करने के लिए मजबूर करता है):

$ $ find . -type l -iname "foo" | xargs rm -i

व्यक्तिगत रूप से मैं -exec trash {} \;फ़ाइलों को अस्थायी रूप से हटाने के लिए उपयोग करता हूं , क्योंकि मैं, अपने आप की तरह, rmअतीत में जल गया हूं । डबल गलत -deleteध्वज के लिए जाता है ।

http://slackermedia.ml/trashy


1
-डेली के बजाय आप इसे प्रिंट कर सकते हैं और इसे xargs में पास कर सकते हैं: find . -type l -iname "foo" | xargs rm -i यह अधिक सुरक्षित है।
बोबन पी।

1
मुझे निश्चित रूप से rm -iसुरक्षा के लिए @ याकूब का उपयोग पसंद है।
कलुआतु वॉन श्लेकर

3
"यह वर्तमान निर्देशिका में सभी सिमलिंक को हटा देगा" ... और इसके नीचे कोई भी बिंदु।
जोसेफ आर।

1
जैसा कि @ जोसेफ। कहा, यह सड़क से नीचे तक जाएगा। Add -maxdepth 1 खोजने में।
बोबन पी।

1
अभी भी रिक्त स्थान के साथ फ़ाइल नाम पर टूट जाता है। के -print0लिए findऔर के -0लिए उपयोग कर सुझाव दें xargs
वाइल्डकार्ड

4
zsh -c 'rm foo(@)'

@एक ग्लोब क्वालिफायर है ; पैटर्न foo(@)क्या fooमेल खाता है, लेकिन केवल प्रतीकात्मक लिंक।

foo(-@)केवल टूटे हुए प्रतीकात्मक लिंक से मेल खाएगा। foo(@,L0)केवल प्रतीकात्मक लिंक और खाली फ़ाइलों का मिलान करेगा।

बेशक, अगर आप पहली बार में zsh चला रहे हैं, तो आपको बस टाइप करने की जरूरत है rm foo(@)Enterटाइपिंग से पहले प्रेस न करने के लिए आपको ध्यान रखना होगा (@)


1
जब मैं इस तरह से उत्तर देखता हूं तो Zsh अधिक और अधिक शक्तिशाली लगता है।
जेफ स्कालर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.