फ़ाइल नाम में रिक्त स्थान, हाइफ़न और अंडरस्कोर हटाएं?


10

एक निर्देशिका, या चयनित फ़ाइलों में रिक्त स्थान, हाइफ़न और अंडरस्कोर को हटाने के लिए एक अच्छी कमांड क्या है?

मैं फ़ाइल नाम को धीमा करने के लिए थूनर कस्टम क्रियाओं के साथ निम्न कमांड का उपयोग करता हूं:

for file in %N; do mv "$file" "$(echo "$file" | tr -s ' ' | tr ' A-Z' '-a-z' | tr -s '-' | tr -c '[:alnum:][:cntrl:].' '-')"; done

लेकिन यह आदेश केवल डैश / हाइफ़न और लोअरकेस के छायांकित वर्णों के साथ रिक्त स्थान को प्रतिस्थापित करता है।

मैंने एक फ़ोल्डर में हजारों फ़ाइलनामों से रिक्त स्थान को हटाने के लिए टर्मिनल में निम्नलिखित कमांड का उपयोग किया है, और यह बहुत तेजी से काम करता है:

 rename "s/ //g" *

फिर, यह केवल रिक्त स्थान हटाता है, और हाइफ़न / डैश और अंडरस्कोर भी नहीं करता है।

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


2
मैं एक समस्या पर ध्यान देता हूं कि बहुत सारे प्रस्तावित समाधानों में फ़ाइल को mv'ing करने से पहले "नए" नाम की मौजूदगी की ठीक से जाँच नहीं हो रही है। ऐसा नहीं करना बहुत सारी समस्याओं का संभावित स्रोत हो सकता है।
mdpc

क्या इसके लिए जाँच करने के लिए John1024 की कमांड को संशोधित करना संभव है?
user8547

@ user8547rename -i "s/[-_ ]//g" *
स्पार्कहॉक

साभार स्पार्कहॉक संयोग से, यह एक थूनर कस्टम एक्शन के रूप में उपयोग करने के इच्छुक लोगों के लिए, थूनर के लिए कमांड है:% N में फाइल के लिए; mv "$ फ़ाइल" echo $file | sed -e 's/[ _-]//g'; किया
user8547

जवाबों:


11

पैकेज के renameसाथ आने वाला संस्करण perlनियमित अभिव्यक्ति का समर्थन करता है:

rename "s/[-_ ]//g" *

वैकल्पिक रूप से,

rename -i "s/[-_ ]//g" *

-iझंडा बनाने जाएगा renameचुपचाप ओवरराइटिंग के बजाय, इंटरैक्टिव मोड का उपयोग करें, जिससे उत्साहित होकर यदि लक्ष्य पहले से मौजूद है।

कभी-कभी पर्ल का नाम बदल दिया जाता है prename

पर्ल का नाम बनाम उपयोग-लिनेक्स का नाम

डेबियन जैसी प्रणालियों पर, पर्ल का नाम डिफ़ॉल्ट लगता है और उपरोक्त कमांड को बस काम करना चाहिए।

कुछ वितरणों पर, renameउपयोग-लिनेक्स से उपयोगिता डिफ़ॉल्ट है। यह उपयोगिता पर्ल के साथ पूरी तरह से असंगत है rename

  • सभी: सबसे पहले, यह देखने के लिए जांचें कि क्या पर्ल renameनाम के तहत उपलब्ध है prename

  • डेबियन: पर्ल का नाम डिफ़ॉल्ट होना चाहिए। यह भी उपलब्ध है prenamerenameनिष्पादन योग्य है, हालांकि, के नियंत्रण में है /etc/alternativesऔर इस तरह कुछ अलग करने के लिए परिवर्तित किया जा सकता था।

  • आर्कलिनक्स: रन pacman -S perl-renameऔर कमांड के रूप में उपलब्ध है perl-rename। अधिक सुविधाजनक नाम के लिए, एक उपनाम बनाएं। (हैट टिप: छेनीलेबस)

  • Mac OSX इस उत्तर के अनुसार , renamehomeXw के माध्यम से OSX पर स्थापित किया जा सकता है:

    brew install rename 
  • डायरेक्ट डाउनलोड: rename पर्ल मॉन्क्स से भी उपलब्ध है:

     wget 'http://www.perlmonks.org/?displaytype=displaycode;node_id=303814' -O rename

मुझे लगता है कि renameआप किस बारे में बात कर रहे हैं, इस पर निर्भर करता है । उपयोग - लिनेक्स -2.24.2-1.fc20.x86_64 से एक नियमित अभिव्यक्ति का समर्थन नहीं करता है।
क्रिस्टियन सियुपिटु 20

1
@CristianCiupitu मैंने सिर्फ उस नाम के संस्करण के लिए मैन पेज की जाँच की जो आपको मिला था। तर्कों के आधार पर, renameओपी का उपयोग perlसंस्करण की तरह दिखता है न कि util-linuxसंस्करण की तरह।
John1024

रिकॉर्ड के लिए, यह उपयोग -लिनक्स संस्करण के renameलिए मैन पेज है । वैसे भी, उस नोट के अलावा, महत्वपूर्ण बात यह है कि ओपी को उसका जवाब मिला (और आप मुझ से एक अपवित्र हैं :- डी)।
क्रिस्चियन सियुपिटु

@CristianCiupitu कि खोजने के लिए धन्यवाद। एक +1 के साथ आप पर वापस।
जॉन 1024

1
@ जॉन 1024 आर्चलिनक्स, लेकिन मुझे पता चला कि कैसे, बस pacman -S perl-renameफिर मैं अनुमान लगा सकता हूं।
चिसेलेड्सबस


4

गिनती नहीं mv, आपको वास्तव में इसके लिए एक बाहरी प्रक्रिया की आवश्यकता नहीं है - आप उन्हें केवल पूफ कर सकते हैं।

ifsqz() ( LC_ALL=C sqz=$1
    isf() { [ -e "$1" ] || [ -L "$1" ] ; }  
    set -- * ; set -f
    for f do isf "$f" || break
    IFS=$sqz; set -- $f; IFS=
    isf "$*" || mv -- "$f" "$*"
    done
)

हालांकि, इसका मतलब है कि mvप्रति फ़ाइल एक मंगलाचरण, और इसलिए शायद renameबेहतर है। हालांकि यह केवल दिए गए काम करना चाहिए एक POSIX mvमें $PATHऔर एक POSIX खोल।

इसलिए, मैं इसके लिए एक तरह का क्रेजी डेमो लेकर आया हूं। परीक्षण सेट की तरह उत्पन्न होता है:

tee - - - - <<CGEN |\
dd cbs=90 conv=unblock |\
sed 'G;$!N'";s/^/touch -- '/;s/$/'/" |sh
$( #BEGIN CGEN
   LC_ALL=C
   i= n='"$((i=((i=i+1)==10||i==39||i==47)>0?(i+1):i))"'
   printf '%b -_   ---___'  $(
   IFS=0; eval \
       printf '"\\\\%04o\\\\%04o "' "$(
       printf "$n"' "$i" '%s $(
       printf %.252d
#END
))"))
CGEN

पहली जगह में मैं यह स्वीकार करने वाला पहला व्यक्ति बनूँगा कि उपरोक्त कमांड ऐसे परिणाम उत्पन्न करता है जो अन्य माध्यमों से अधिक आसानी से प्राप्त किए जा सकते हैं। लेकिन अन्य साधनों के साथ $IFS- साथ और थोड़ी (बीमार?) कल्पना के साथ भी क्या किया जा सकता है, इसका प्रदर्शन नहीं किया जाएगा ।

तो पहला बिट काफी सीधा-आगे है:

  • tee इसके इनपुट की 5 प्रतियों को बाहर निकालता है - जिसे हेरिडेक्जिमेंट कहा जाता है CGEN

  • dd 90 बाइट्स प्रति ब्लॉक और पाइप्स पर newlines द्वारा इसके इनपुट को ब्लॉक करता है ...

  • sedउन दो खंडों में से 2 को दो \nइललाइन वर्णों पर जोड़ देता है, जो 'एकल-परिणाम का उद्धरण देता है, और touch --हर पाइप चक्र के लिए स्ट्रिंग को प्री - आउट करता है ...

  • sh जो तब शेल कमांड के रूप में सभी इनपुट को निष्पादित करता है

#CGENबिट हालांकि ... ठीक है, संक्षेप में ...

  • नीचे का printfनिशान 252 0 s है

  • पिछले से अगले 252 ''अशक्त तर्क प्राप्त करता है और प्रत्येक के $nलिए स्ट्रिंग द्वारा पीछा की सामग्री प्रिंट" $i "

  • evalअगले व्याख्या के तर्क की व्याख्या करने printfसे पहले उस व्याख्या के परिणामों को प्रिंट करता है क्योंकि अष्टक अंक 2 बैकस्लैश द्वारा एक टुकड़ा होता है

  • अंतिम printfउन ऑक्टल्स के लिए बाइट के मानों को एक बार में -_ ---___प्रत्येक जोड़े के लिए स्ट्रिंग द्वारा प्रिंट करता है

  • $nएक समीकरण के लिए शुरू किया जाता है जो $iहर मूल्यांकन के लिए एक-एक करके बढ़ेगा सिवाय इसके कि यह 10, 39 या 47 मानों को छोड़ देता है - (जो क्रमशः ASCII दशमलव में \newline, 'एकल-उद्धरण और /स्लैश हैं)

अंतिम परिणाम एक निर्देशिका है जिसमें बहुत सारे बदसूरत फ़ाइलनाम होते हैं जिनमें 1 से 255 तक हर बाइट में एकल-उद्धरण (केवल एक और sed s///बयान से बचने के लिए छोड़ दिया गया ) और /स्लैश को छोड़कर । वे फ़ाइल नाम इस तरह दिखते हैं:

(set -- *; printf '%s\n\n##############\n\n%s\n' "${9}" "${34}")  | cat -A

   ---___ww -_   ---___xx -_   ---___yy -_   ---___zz -_   ---___{{ -_   ---___|| -_   ---$
$
___}} -_   ---___~~ -_   ---___^?^? -_   ---___M-^@M-^@ -_   ---___M-^AM-^A -_   ---___M-^BM-^B -_   ---___M-^CM-^C$
$
##############$
$
 -_   ---___M-ZM-Z -_   ---___M-[M-[ -_   ---___M-\M-\ -_   ---___M-]M-] -_   ---___M-^M-^ -_   ---___M-_M-_ -_$
$
---___M-`M-` -_   ---___M-aM-a -_   ---___M-bM-b -_   ---___M-cM-c -_   ---___M-dM-d -_   ---___M-eM-e -_   ---___$

अब मुझे इन फाइलों पर कुछ डेटा मिलेगा:

chksqz() ( LC_ALL=C sqz=$1
    set -- * ; set -f ; IFS= ; tc="$*"
    printf '#%s\n' \
        "There are $# files in this test directory." \
        "All filenames combined contain a total of ${#tc} bytes."
    IFS=$sqz ; set -- $* ; IFS= ; sc="$*"  
    printf "%s '$sqz'" \
        "#Of which ${#sc} bytes are not"\
        " and $((${#tc}-${#sc})) bytes are"
    set +f ; unset IFS
    printf ".\n#%s\n#Total:\t%d\n#Other:\t%d\n#'$sqz':\t%d\n" \
        "And to confirm these figures:" \
        $(  printf %s * | wc -c 
            printf %s * | tr -d "$sqz" | wc -c
            printf %s * | tr -dc "$sqz" | wc -c
))
chksqz '_ -'

आउटपुट

#There are 101 files in this test directory.
#All filenames combined contain a total of 17744 bytes.
#Of which 2692 bytes are not '_ -' and 15052 bytes are '_ -'.
#And to confirm these figures:
#Total: 17744
#Other: 2692
#'_ -': 15052

ठीक है। अब अंत में, कार्रवाई करने के लिए:

ifsqz '_ -'
chksqz '_ -'

आउटपुट

#There are 101 files in this test directory.
#All filenames combined contain a total of 2692 bytes.
#Of which 2692 bytes are not '_ -' and 0 bytes are '_ -'.
#And to confirm these figures:
#Total: 2692
#Other: 2692
#'_ -': 0

सफलता! आप अपने लिए देख सकते है:

ls

????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????
??????????????????????
????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
??????????????????????????
????????????????????????
????????????????????
??????????????????
????????????????????????????
??
????????????????????????????
??????????????????????????
????????????????????????????
????????????????????????????
????????????????????!!""##
??????????????????!!""##$$
????????????????!!""##$$%%
????????????!!""##$$%%&&((
????????!!""??##$$%%&&(())
$$%%&&(())**??++,,..0011
%%&&(())**++??,,..00112233
&&(())**++,,??..0011223344
))**++,,..??0011223344556
**++,,..00??11223344556677
22334455667788??99::;;<<==>>
445566778899??::;;<<==>>??@@
5566778899::;;??<<==>>??@@AA
6778899::;;<<??==>>??@@AABB
8899::;;<<==??>>??@@AABBCCDD
\\]]^^``aa??bbccddeeffgghh
]]^^``aabbc??cddeeffgghhii
^^``aabbccdd??eeffgghhiijj
??@@AABBCCDDEE??FFGGHHIIJJKK
AABBCCDDEEFF??GGHHIIJJKKLLM
BBCCDDEEFFGG??HHIIJJKKLLMMNN
CCDDEEFFGGHHII??JJKKLLMMNNOO
EEFFGGHHIIJJ??KKLLMMNNOOPPQQ
ffgghhiijjkk??llmmnnooppqqrr
gghhiijjkkllmm??nnooppqqrrss
iijjkkllmmnn??ooppqqrrsstt
jjkkllmmnnoo??ppqqrrssttuuvv
kkllmmnnooppqq??rrssttuuvvww
LLMMNNOOPPQQRR??SSTTUUVVWWXX
MNNOOPPQQRRSS??TTUUVVWWXXYY
OOPPQQRRSSTT??UUVVWWXXYYZZ[[
PPQQRRSSTTUUVV??WWXXYYZZ[[\\
RRSSTTUUVVWW??XXYYZZ[[\\]]
ssttuuvvwwxx??yyzz{{||}}~~??
ttuuvvwwxxyyz??z{{||}}~~????
uuvvwwxxyyzz{{??||}}~~??????
wwxxyyzz{{||??}}~~??????????
xxyyzz{{||}}~~??????????????
YYZZ[[\\]]^^??``aabbccddee
ZZ[[\\]]^^``??aabbccddeeff

2
की एक रचनात्मक इस्तेमाल के लिए +1 IFS+printf
John1024

@ John1024 - वास्तव में क्या मजेदार है:set -- 'some arbitrary' args; eval printf '"%s\n"' "$(IFS=0; printf ' "$@" %s' $(printf %025d))"
mikeserv

1
new="$(IFS=" -_"; printf %s $1)"एक उपखंड (ksh93 को छोड़कर) की मांग करता है और टेललाइनिंग के साथ मुद्दे हैं। एक अन्य विकल्प का उपयोग करें IFS=' -_'; set -- $1; IFS=; new="$*"(और लूप के लिए अपने समय को बदलने के लिए)
स्टीफन चेज़लस

1
[ -e x ]यदि xकोई गैर-मौजूदा या गैर-पहुंच वाली फ़ाइल के लिए एक सहिष्णु है, तो गलत वापस आ जाएगी ।
स्टीफन चेज़लस

1
अच्छा खोल कुंग-फू!
काउंटरमोड

2

यदि आपके पास पर्ल है, तो आपके पास आमतौर पर नाम है। तुम कर सकते हो:

> type rename
rename is /usr/bin/rename

और दिखाएं कि यह स्क्रिप्ट कैसे लिखी गई है:

> cat /usr/bin/rename | head -n 5 #firt 5 lines for example
#!/usr/bin/perl -w
#
#  This script was developed by Robin Barker (Robin.Barker@npl.co.uk),
#  from Larry Wall's original script eg/rename from the perl source.
#

यह स्क्रिप्ट -i ध्वज का समर्थन नहीं करता है (यह मेरे सिस्टम में संस्करण है), लेकिन शायद आपका समर्थन करता है। तर्कों का क्या। पहले पीसीआर प्रारूप के साथ नियमित अभिव्यक्ति है, यह फिल्टर की तरह काम करता है, इनपुट नाम को आउटपुट नाम में संशोधित करता है। आपके द्वारा दिए गए इनपुट नामों की सूची '*'। उदाहरण के लिए, आप करते हैं:

> cd /tmp
> rename 's/ //g' *

में वास्तविक '*' का विस्तार किया जा सकता है:

> rename 's/ //g' file1 file2 file3 othe files found in current directory

जब आपके पास वास्तव में बड़ी गिनती फाइलें होती हैं, तो आप जाल में होते हैं। शेल सिस्टम एक्सेप्ट की तुलना में आपकी लाइन का विस्तार करेगा। तब आप खोज या xargs का उपयोग करके वर्कअराउंड कर सकते हैं। 'खोज' का उपयोग करना समस्या है, क्योंकि नाम बदलने को निर्देशिका में गणना की गई फ़ाइलों के बराबर कई बार कहा जाएगा। -r विकल्प के साथ बेहतर उपयोग xargs। एक नाम बदलें कॉल कई फ़ाइलों को संशोधित करती है। उदाहरण के लिए:

> ls | xargs -r rename 's/ //g'   #thats all, names will be appended at the end of this command.

अंतिम समस्या, इसका क्या मतलब है:

's/ //g'

यह संशोधित नामों के लिए नियमित अभिव्यक्ति है। पहले '/' के बाद अंतरिक्ष है। यह पता चला है, और दूसरी '/' के बाद स्ट्रिंग द्वारा प्रतिस्थापित किया गया है। लेकिन तीसरे '/' के साथ खाली स्ट्रिंग समाप्त हो जाती है, फिर अंतरिक्ष को कुछ भी नहीं बदला जाता है। विकल्प 'जी' इस अभिव्यक्ति को दोहराता है। अभिव्यक्ति सभी नामों के लिए शुरू से अंत तक चलेगी, और सभी स्थानों का पता लगाती है।

लेकिन क्या होगा अगर आपके पास टैब चरित्र या अन्य 'सफेद' चरित्र है? इस 's' के लिए प्रतिस्थापन है। अन्य अनावश्यक चरित्र क्या हैं? बस इसे अभिव्यक्ति में जोड़ें। उदाहरण के लिए, कोष्ठक के साथ सभी पास:

's/[\s_-]//g'

बस इतना ही। क्या आपको समानता दिखती है? मुझे लगता है कि आपको मैन पर्क्रेक्विक और मैन पेर्लटुट पढ़ना चाहिए, यह आपको समझाता है (मुझे आशा है कि) नियमित अभिव्यक्ति कैसे काम करती है। यदि आप की जरूरत है तो आप अपनी खुद की स्क्रिप्ट में नाम बदलने का उपयोग कर सकते हैं।


1

निम्नलिखित shशेल लूप मौजूदा निर्देशिका में फ़ाइलों के नामों से सभी रिक्त स्थान, अंडरस्कोर और डैश को हटा देगा, किसी भी मौजूदा फ़ाइलों को अधिलेखित नहीं करने का ख्याल रखते हुए:

for f in *; do
    test -f "$f" || continue
    nf=$( echo "$f" | tr -d ' _-' )
    ! test -e "$nf" && echo mv "$f" "$nf"
done

के लिए bashऔर ksh, और तर्क के साथ किया जा रहा है थोड़ा और अधिक वर्बोज़:

for f in *; do
    if [[ -f "$f" ]]; then
        nf=$( tr -d ' _-' <<<"$f" )
        if [[ ! -e "$nf" ]]; then
            echo mv "$f" "$nf"
        fi
    fi
done

echoजब आप निश्चित हों , तो उसे हटा दें जो आप करना चाहते हैं।

trआदेश (नष्ट करेगा -dकिसी भी चरित्र पात्रों में से दिए गए समुच्चय में) ( ' _-')। सेट के बहुत शुरुआत या अंत में डैश होना महत्वपूर्ण है, या इसे वर्णों की श्रेणी के रूप में व्याख्या किया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.