दिलचस्प पोस्ट
क्या __LINE__ __FILE__ बराबर C # में मौजूद है? मैं सी # में एक बाइट सरणी से हैशोड कैसे उत्पन्न करूं? मोबाइल ब्राउज़र में स्क्रॉलबार दृश्यमान बनाएं लिनक्स पर विलंबित और छोड़े गए पैकेट का अनुकरण करें Autowired निर्भरता का इंजेक्शन विफल; आर में केस स्टेटमेंट समतुल्य एनजीएनएक्स में एक यूआरएल रीराइट लिखने के लिए कैसे? जावा में SHA-256 के माध्यम से हैश स्ट्रिंग एंड्रॉइड डिफ़ॉल्ट डिफ़ॉल्ट एसएमएस ऐप PHP में सरणी के लिए ऑपरेटर? JQuery के AJAX प्रतिक्रिया एचटीएमएल के साथ डिव अद्यतन करें ग्रहण त्रुटि संदेश देता है "जावा प्रारंभ किया गया था, लेकिन निकासी कोड = 1 लौटा" COM इंटरॉप घटक में एक साधारण सी # डीएलएल को चालू करें क्या PHP पीडीओ वक्तव्य पैरामीटर के रूप में तालिका या स्तंभ नाम स्वीकार कर सकता है? PHP – डॉट नेशन कुंजी के साथ 2 डी सरणी के लिए बहुआयामी सरणी को परिवर्तित करें

बास में फ़ाइल नाम और एक्सटेंशन निकालें

मैं फ़ाइल नाम (एक्सटेंशन के बिना) और एक्सटेंशन को अलग से प्राप्त करना चाहता हूं।

मैंने अभी तक पाया सबसे अच्छा समाधान है:

NAME=`echo "$FILE" | cut -d'.' -f1` EXTENSION=`echo "$FILE" | cut -d'.' -f2` 

यह गलत है क्योंकि यह फ़ाइल नाम में एकाधिक "।" वर्ण। यदि, चलो, कहते हैं, मैं abjs है यह और बी.जे. , बजाय एबी और जे एस विचार करेंगे।

इसे आसानी से पायथन में किया जा सकता है

 file, ext = os.path.splitext(path) 

लेकिन अगर मैं संभव हो तो इसके लिए मैं एक पायथन इंटरप्रेटर को आग्रह नहीं करना चाहूंगा

कोई बेहतर विचार?

Solutions Collecting From Web of "बास में फ़ाइल नाम और एक्सटेंशन निकालें"

सबसे पहले, पथ के बिना फ़ाइल नाम प्राप्त करें:

 filename=$(basename "$fullfile") extension="${filename##*.}" filename="${filename%.*}" 

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

 filename="${fullfile##*/}" 
 ~% FILE="example.tar.gz" ~% echo "${FILE%%.*}" example ~% echo "${FILE%.*}" example.tar ~% echo "${FILE#*.}" tar.gz ~% echo "${FILE##*.}" gz 

अधिक विवरण के लिए, बाश मैनुअल में शेल पैरामीटर विस्तार देखें।

आम तौर पर आप पहले से ही एक्सटेंशन को जानते हैं, इसलिए आप इसका उपयोग करना चाह सकते हैं:

 basename filename .extension 

उदाहरण के लिए:

 basename /path/to/dir/filename.txt .txt 

और हम मिलते हैं

 filename 

आप POSIX चर के जादू का उपयोग कर सकते हैं:

 bash-3.2$ FILENAME=somefile.tar.gz bash-3.2$ echo ${FILENAME%%.*} somefile bash-3.2$ echo ${FILENAME%.*} somefile.tar 

इसमें एक चेतावनी है कि अगर आपका फ़ाइल नाम फॉर्म का था। ./somefile.tar.gz तो echo ${FILENAME%%.*} करें . और आपके पास खाली स्ट्रिंग है।

(आप उस अस्थायी चर के साथ काम कर सकते हैं:

 FULL_FILENAME=$FILENAME FILENAME=${FULL_FILENAME##*/} echo ${FILENAME%%.*} 

)


यह साइट अधिक बताती है।

 ${variable%pattern} Trim the shortest match from the end ${variable##pattern} Trim the longest match from the beginning ${variable%%pattern} Trim the longest match from the end ${variable#pattern} Trim the shortest match from the beginning 

ऐसा लगता नहीं है कि फाइल में कोई एक्सटेंशन नहीं है, या कोई फ़ाइल नाम नहीं है। यहाँ मैं क्या कर रहा हूँ; यह केवल बिल्टिन्स का उपयोग करता है और अधिक (लेकिन सभी) रोगविज्ञानी फाइलनामों को संभालता है

 #!/bin/bash for fullpath in "$@" do filename="${fullpath##*/}" # Strip longest match of */ from start dir="${fullpath:0:${#fullpath} - ${#filename}}" # Substring from 0 thru pos of filename base="${filename%.[^.]*}" # Strip shortest match of . plus at least one non-dot char from end ext="${filename:${#base} + 1}" # Substring from len of base thru end if [[ -z "$base" && -n "$ext" ]]; then # If we have an extension and no base, it's really the base base=".$ext" ext="" fi echo -e "$fullpath:\n\tdir = \"$dir\"\n\tbase = \"$base\"\n\text = \"$ext\"" done 

और यहां कुछ टेस्टकेज़ हैं:

 $ basename- और-extension.sh / / home / me / / home / me / file /home/me/file.tar /home/me/file.tar.gz /home/me/.hidden / home / me / .hidden.tar / home / me / ..
 /:
     dir = "/"
     बेस = ""
     ext = ""
 /घर मुझे/:
     dir = "/ घर / मी /"
     बेस = ""
     ext = ""
 / घर / मुझे / फ़ाइल:
     dir = "/ घर / मी /"
     base = "file"
     ext = ""
 /home/me/file.tar:
     dir = "/ घर / मी /"
     base = "file"
     ext = "tar"
 /home/me/file.tar.gz:
     dir = "/ घर / मी /"
     base = "file.tar"
     ext = "gz"
 /home/me/.hidden:
     dir = "/ घर / मी /"
     base = ".hidden"
     ext = ""
 /home/me/.hidden.tar:
     dir = "/ घर / मी /"
     base = ".hidden"
     ext = "tar"
 /घर मुझे/..:
     dir = "/ घर / मी /"
     बेस = ".."
     ext = ""
 ।:
     dir = ""
     बेस = "।"
     ext = ""

आप basename उपयोग कर सकते हैं

उदाहरण:

 $ basename foo-bar.tar.gz .tar.gz foo-bar 

आपको एक्सटेंशन के साथ बेसएनाम प्रदान करने की ज़रूरत है, जिसे निकाला जा सकता है, हालांकि अगर आप हमेशा -z साथ tar निष्पादित करते हैं तो आप जानते हैं कि विस्तार होगा .tar.gz

यह आपको करना चाहिए जो करना चाहिए:

 tar -zxvf $1 cd $(basename $1 .tar.gz) 

आप पिछले दो एक्सटेंशन ( ".tar.gz" भाग) को निकालने के लिए cut कमांड का उपयोग कर सकते हैं:

 $ echo "foo.tar.gz" | cut -d'.' --complement -f2- foo 

जैसा क्लेटन ह्यूजेस द्वारा एक टिप्पणी में बताया गया है, यह सवाल में वास्तविक उदाहरण के लिए काम नहीं करेगा। तो एक विकल्प के रूप में मैं विस्तारित नियमित अभिव्यक्ति के साथ sed का प्रयोग करने का प्रस्ताव देता हूं, जैसे:

 $ echo "mpc-1.0.1.tar.gz" | sed -r 's/\.[[:alnum:]]+\.[[:alnum:]]+$//' mpc-1.0.1 

यह पिछले दो (अल्फा-न्यूमेरिक) विस्तार को बिना शर्त बिना निकाल कर काम करता है

[एंडर्स लिंडाहल से टिप्पणी के बाद अपडेट किया गया]

Mellen एक ब्लॉग पोस्ट पर एक टिप्पणी में लिखते हैं:

बैश का उपयोग, विस्तार के बिना फ़ाइल नाम प्राप्त करने के लिए ${file%.*} और अकेले विस्तार प्राप्त करने के लिए ${file##*.} है। अर्थात्,

 file="thisfile.txt" echo "filename: ${file%.*}" echo "extension: ${file##*.}" 

आउटपुट:

 filename: thisfile extension: txt 

यहां कुछ वैकल्पिक सुझाव दिए गए हैं (अधिकतर में awk ), जिनमें कुछ उन्नत उपयोग के मामले शामिल हैं, जैसे सॉफ्टवेयर पैकेज के लिए संस्करण संख्या निकालने

 f='/path/to/complex/file.1.0.1.tar.gz' # Filename : 'file.1.0.x.tar.gz' echo "$f" | awk -F'/' '{print $NF}' # Extension (last): 'gz' echo "$f" | awk -F'[.]' '{print $NF}' # Extension (all) : '1.0.1.tar.gz' echo "$f" | awk '{sub(/[^.]*[.]/, "", $0)} 1' # Extension (last-2): 'tar.gz' echo "$f" | awk -F'[.]' '{print $(NF-1)"."$NF}' # Basename : 'file' echo "$f" | awk '{gsub(/.*[/]|[.].*/, "", $0)} 1' # Basename-extended : 'file.1.0.1.tar' echo "$f" | awk '{gsub(/.*[/]|[.]{1}[^.]+$/, "", $0)} 1' # Path : '/path/to/complex/' echo "$f" | awk '{match($0, /.*[/]/, a); print a[0]}' # or echo "$f" | grep -Eo '.*[/]' # Folder (containing the file) : 'complex' echo "$f" | awk -F'/' '{$1=""; print $(NF-1)}' # Version : '1.0.1' # Defined as 'number.number' or 'number.number.number' echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' # Version - major : '1' echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f1 # Version - minor : '0' echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f2 # Version - patch : '1' echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f3 # All Components : "path to complex file 1 0 1 tar gz" echo "$f" | awk -F'[/.]' '{$1=""; print $0}' # Is absolute : True (exit-code : 0) # Return true if it is an absolute path (starting with '/' or '~/' echo "$f" | grep -q '^[/]\|^~/' 

इंटरमीडिएट परिणामों के आधार पर बिना उपयोग के सभी मामलों में मूल पूर्ण पथ का उपयोग इनपुट के रूप में किया जाता है।

 pax> echo abjs | sed 's/\.[^.]*$//' ab pax> echo abjs | sed 's/^.*\.//' js 

ठीक काम करता है, तो आप इसका उपयोग कर सकते हैं:

 pax> FILE=abjs pax> NAME=$(echo "$FILE" | sed 's/\.[^.]*$//') pax> EXTENSION=$(echo "$FILE" | sed 's/^.*\.//') pax> echo $NAME ab pax> echo $EXTENSION js 

आज्ञाओं, वैसे, काम इस प्रकार है।

NAME लिए कमांड एक "." चरित्र के किसी भी संख्या के बाद गैर- "." लाइन के अंत तक वर्ण, कुछ भी नहीं के साथ (यानी, यह अंतिम से सभी को हटा देता है "." रेखा के अंत तक, समावेशी)। मूल रूप से यह एक गैर-लालची प्रतिस्थापन है जो कि रेगेक्स ट्रिकरी का उपयोग कर रहा है।

EXTENSION लिए कमांड एक "." रेखा की शुरुआत में चरित्र, कुछ भी नहीं के साथ (यानी, यह लाइन की शुरुआत से अंतिम बिंदु, समावेशी तक सब कुछ निकाल देता है)। यह एक लालची प्रतिस्थापन है जो कि डिफ़ॉल्ट कार्यवाही है I

मुझे लगता है कि अगर आपको फ़ाइल के नाम की आवश्यकता है, तो आप यह कोशिश कर सकते हैं:

 FULLPATH=/usr/share/X11/xorg.conf.d/50-synaptics.conf # Remove all the prefix until the "/" character FILENAME=${FULLPATH##*/} # Remove all the prefix until the "." character FILEEXTENSION=${FILENAME##*.} # Remove a suffix, in our case, the filename. This will return the name of the directory that contains this file. BASEDIRECTORY=${FULLPATH%$FILENAME} echo "path = $FULLPATH" echo "file name = $FILENAME" echo "file extension = $FILEEXTENSION" echo "base directory = $BASEDIRECTORY" 

और वह सब = डी है।

[एक एक लाइनर से एक सामान्य बैश फ़ंक्शन पर संशोधित, व्यवहार अब dirname और basename उपयोगिताओं के साथ संगत; तर्क जोड़ा गया।]

स्वीकार किए जाते हैं उत्तर विशिष्ट मामलों में अच्छी तरह से काम करता है , लेकिन किन मामलों में विफल रहता है , अर्थात्:

  • एक्सटेंशन के बिना फाइलनामों के लिए (इस उत्तर के शेष भाग में प्रत्यय कहा जाता है), extension=${filename##*.} एक खाली स्ट्रिंग के बजाय इनपुट फ़ाइल नाम देता है।
  • extension=${filename##*.} प्रारंभिक में शामिल नहीं है , सम्मेलन के विपरीत
    • अंधा अंधेरे में तैयारी प्रत्यय के बिना फ़ाइल नाम के लिए काम नहीं करेगा
  • filename="${filename%.*}" रिक्त स्ट्रिंग होगी, अगर इनपुट फ़ाइल नाम से शुरू होता है और इसमें कोई और नहीं है वर्ण (जैसे, .bash_profile ) – सम्मेलन के विपरीत।

———

इस प्रकार, एक मजबूत समाधान की जटिलता जो सभी किनारे वाले मामलों को कवर करती है एक फ़ंक्शन के लिए कॉल करती है – नीचे इसकी परिभाषा देखें; यह एक पथ के सभी घटकों को वापस कर सकता है

उदाहरण कॉल:

 splitPath '/etc/bash.bashrc' dir fname fnameroot suffix # -> $dir == '/etc' # -> $fname == 'bash.bashrc' # -> $fnameroot == 'bash' # -> $suffix == '.bashrc' 

ध्यान दें कि इनपुट पथ के बाद तर्क आज़ादी से चुने गए हैं, स्थितीय चर नाम हैं
उन हितों की संख्या को छोड़ने के लिए जो उन लोगों से पहले आते हैं, को निर्दिष्ट करें _ (फेंक-दूर चर $_ का उपयोग करने के लिए) या '' ; उदाहरण के लिए, केवल फ़ाइलनाम रूट और एक्सटेंशन निकालने के लिए, splitPath '/etc/bash.bashrc' _ _ fnameroot extension


 # SYNOPSIS # splitPath path varDirname [varBasename [varBasenameRoot [varSuffix]]] # DESCRIPTION # Splits the specified input path into its components and returns them by assigning # them to variables with the specified *names*. # Specify '' or throw-away variable _ to skip earlier variables, if necessary. # The filename suffix, if any, always starts with '.' - only the *last* # '.'-prefixed token is reported as the suffix. # As with `dirname`, varDirname will report '.' (current dir) for input paths # that are mere filenames, and '/' for the root dir. # As with `dirname` and `basename`, a trailing '/' in the input path is ignored. # A '.' as the very first char. of a filename is NOT considered the beginning # of a filename suffix. # EXAMPLE # splitPath '/home/jdoe/readme.txt' parentpath fname fnameroot suffix # echo "$parentpath" # -> '/home/jdoe' # echo "$fname" # -> 'readme.txt' # echo "$fnameroot" # -> 'readme' # echo "$suffix" # -> '.txt' # --- # splitPath '/home/jdoe/readme.txt' _ _ fnameroot # echo "$fnameroot" # -> 'readme' splitPath() { local _sp_dirname= _sp_basename= _sp_basename_root= _sp_suffix= # simple argument validation (( $# >= 2 )) || { echo "$FUNCNAME: ERROR: Specify an input path and at least 1 output variable name." >&2; exit 2; } # extract dirname (parent path) and basename (filename) _sp_dirname=$(dirname "$1") _sp_basename=$(basename "$1") # determine suffix, if any _sp_suffix=$([[ $_sp_basename = *.* ]] && printf %s ".${_sp_basename##*.}" || printf '') # determine basename root (filemane w/o suffix) if [[ "$_sp_basename" == "$_sp_suffix" ]]; then # does filename start with '.'? _sp_basename_root=$_sp_basename _sp_suffix='' else # strip suffix from filename _sp_basename_root=${_sp_basename%$_sp_suffix} fi # assign to output vars. [[ -n $2 ]] && printf -v "$2" "$_sp_dirname" [[ -n $3 ]] && printf -v "$3" "$_sp_basename" [[ -n $4 ]] && printf -v "$4" "$_sp_basename_root" [[ -n $5 ]] && printf -v "$5" "$_sp_suffix" return 0 } test_paths=( '/etc/bash.bashrc' '/usr/bin/grep' '/Users/jdoe/.bash_profile' '/Library/Application Support/' 'readme.new.txt' ) for p in "${test_paths[@]}"; do echo ----- "$p" parentpath= fname= fnameroot= suffix= splitPath "$p" parentpath fname fnameroot suffix for n in parentpath fname fnameroot suffix; do echo "$n=${!n}" done done 

कार्य का अभ्यास करने वाला टेस्ट कोड:

 test_paths=( '/etc/bash.bashrc' '/usr/bin/grep' '/Users/jdoe/.bash_profile' '/Library/Application Support/' 'readme.new.txt' ) for p in "${test_paths[@]}"; do echo ----- "$p" parentpath= fname= fnameroot= suffix= splitPath "$p" parentpath fname fnameroot suffix for n in parentpath fname fnameroot suffix; do echo "$n=${!n}" done done 

अपेक्षित आउटपुट – बढ़त के मामलों को नोट करें:

  • एक फ़ाइल नाम कोई प्रत्यय नहीं है
  • एक फ़ाइल नाम से शुरू होता है (प्रत्यय की शुरुआत नहीं माना गया)
  • अंत में एक इनपुट पथ / (अनुक्रम / अनदेखी की जाती है)
  • एक इनपुट पथ जो केवल फ़ाइल नाम है . (मूल पथ के रूप में लौटाया जाता है)
  • एक फ़ाइल नाम जो कि अधिक से अधिक है -प्रेरिकेड टोकन (केवल अंतिम प्रत्यय माना जाता है):
 ----- /etc/bash.bashrc parentpath=/etc fname=bash.bashrc fnameroot=bash suffix=.bashrc ----- /usr/bin/grep parentpath=/usr/bin fname=grep fnameroot=grep suffix= ----- /Users/jdoe/.bash_profile parentpath=/Users/jdoe fname=.bash_profile fnameroot=.bash_profile suffix= ----- /Library/Application Support/ parentpath=/Library fname=Application Support fnameroot=Application Support suffix= ----- readme.new.txt parentpath=. fname=readme.new.txt fnameroot=readme.new suffix=.txt 

आप सभी फ़ील्ड और उसके बाद वाले जोड़ने - फ़ील्ड नंबर को प्रदर्शित करने के लिए कटौती कर सकते हैं।

 NAME=`basename "$FILE"` EXTENSION=`echo "$NAME" | cut -d'.' -f2-` 

इसलिए यदि FILE eth0.pcap.gz , तो विस्तार pcap.gz होगा

उसी तर्क का उपयोग करके, आप '-' का उपयोग कर फाइल नाम को भी नीचे ला सकते हैं:

 NAME=`basename "$FILE" | cut -d'.' -f-1` 

यह उन फाइलनामों के लिए भी काम करता है, जिनके पास कोई एक्सटेंशन नहीं है।

इस सरल कार्य के लिए awk या sed या perl साथ परेशान करने की कोई आवश्यकता नहीं है। एक शुद्ध-बैश, os.path.splitext() समाधान जो केवल पैरामीटर विस्तार का उपयोग करता है।

संदर्भ कार्यान्वयन

os.path.splitext(path) का दस्तावेज़ीकरण:

एक जोड़े (root, ext) में पथनाम पथ को विभाजित करें (root, ext) जैसे कि root + ext == path , और ext खाली है या एक अवधि के साथ शुरू होता है और इसमें अधिकतम एक अवधि होती है। बेसएनाम पर प्रमुख अवधि को नजरअंदाज किया जाता है; splitext('.cshrc') देता है ('.cshrc', '') splitext('.cshrc') ('.cshrc', '')

पायथन कोड:

 root, ext = os.path.splitext(path) 

बैश क्रियान्वयन

प्रमुख अवधि का सम्मान करना

 root="${path%.*}" ext="${path#"$root"}" 

प्रमुख अवधि को अनदेखा करना

 root="${path#.}";root="${path%"$root"}${root%.*}" ext="${path#"$root"}" 

टेस्ट

यहां प्रमुख अवधि के कार्यान्वयन को अनदेखा करने के लिए परीक्षण के मामले हैं, जो प्रत्येक इनपुट पर पायथन संदर्भ कार्यान्वयन से मेल खाने चाहिए।

 |---------------|-----------|-------| |path |root |ext | |---------------|-----------|-------| |' .txt' |' ' |'.txt' | |' .txt.txt' |' .txt' |'.txt' | |' txt' |' txt' |'' | |'*.txt.txt' |'*.txt' |'.txt' | |'.cshrc' |'.cshrc' |'' | |'.txt' |'.txt' |'' | |'?.txt.txt' |'?.txt' |'.txt' | |'\n.txt.txt' |'\n.txt' |'.txt' | |'\t.txt.txt' |'\t.txt' |'.txt' | |'a b.txt.txt' |'a b.txt' |'.txt' | |'a*b.txt.txt' |'a*b.txt' |'.txt' | |'a?b.txt.txt' |'a?b.txt' |'.txt' | |'a\nb.txt.txt' |'a\nb.txt' |'.txt' | |'a\tb.txt.txt' |'a\tb.txt' |'.txt' | |'txt' |'txt' |'' | |'txt.pdf' |'txt' |'.pdf' | |'txt.tar.gz' |'txt.tar' |'.gz' | |'txt.txt' |'txt' |'.txt' | |---------------|-----------|-------| 

परीक्षण के परिणाम

सभी परीक्षण पारित

ठीक है, अगर मैं सही ढंग से समझता हूं, तो यहां समस्या यह है कि एक फ़ाइल के नाम और पूर्ण एक्सटेंशन को कैसे प्राप्त करें, जिसमें एकाधिक एक्सटेंशन हैं, जैसे, stuff.tar.gz

यह मेरे लिए काम करता है:

 fullfile="stuff.tar.gz" fileExt=${fullfile#*.} fileName=${fullfile%*.$fileExt} 

यह आपको फ़ाइल नाम और .tar.gz एक्सटेंशन के रूप में stuff देगा। यह 0 सहित किसी भी संख्या में एक्सटेंशन के लिए काम करता है। आशा है कि यह उसी समस्या वाले किसी के लिए मदद करता है =)

जादू फ़ाइल मान्यता

इस स्टैक अतिप्रवाह प्रश्न पर बहुत सारे अच्छे उत्तर के अलावा मैं जोड़ना चाहूंगा:

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

 file myfile.txt myfile.txt: UTF-8 Unicode text file -b --mime-type myfile.txt text/plain 

मानक एक्सटेंशन /etc/mime.types (मेरे डेबियन जीएनयू / लिनक्स डेस्कटॉप पर) में पाया जा सकता है। man file और man mime.types । शायद आपको file उपयोगिता और mime-support संकुल को स्थापित करना होगा):

 grep $( file -b --mime-type myfile.txt ) </etc/mime.types text/plain asc txt text pot brf srt 

आप सही एक्सटेंशन का निर्धारण करने के लिए एक बैश फ़ंक्शन बना सकते हैं। थोड़ा सा (सही नहीं) नमूना है:

 file2ext() { local _mimetype=$(file -Lb --mime-type "$1") _line _basemimetype case ${_mimetype##*[/.-]} in gzip | bzip2 | xz | z ) _mimetype=${_mimetype##*[/.-]} _mimetype=${_mimetype//ip} _basemimetype=$(file -zLb --mime-type "$1") ;; stream ) _mimetype=($(file -Lb "$1")) [ "${_mimetype[1]}" = "compressed" ] && _basemimetype=$(file -b --mime-type - < <( ${_mimetype,,} -d <"$1")) || _basemimetype=${_mimetype,,} _mimetype=${_mimetype,,} ;; executable ) _mimetype='' _basemimetype='' ;; dosexec ) _mimetype='' _basemimetype='exe' ;; shellscript ) _mimetype='' _basemimetype='sh' ;; * ) _basemimetype=$_mimetype _mimetype='' ;; esac while read -a _line ;do if [ "$_line" == "$_basemimetype" ] ;then [ "$_line[1]" ] && _basemimetype=${_line[1]} || _basemimetype=${_basemimetype##*[/.-]} break fi done </etc/mime.types case ${_basemimetype##*[/.-]} in executable ) _basemimetype='' ;; shellscript ) _basemimetype='sh' ;; dosexec ) _basemimetype='exe' ;; * ) ;; esac [ "$_mimetype" ] && [ "$_basemimetype" != "$_mimetype" ] && printf ${2+-v} $2 "%s.%s" ${_basemimetype##*[/.-]} ${_mimetype##*[/.-]} || printf ${2+-v} $2 "%s" ${_basemimetype##*[/.-]} } 

यह फ़ंक्शन एक बैश चर सेट कर सकता है जो बाद में इस्तेमाल किया जा सकता है:

(यह @ पेसेश सही जवाब से प्रेरित है):

 filename=$(basename "$fullfile") filename="${filename%.*}" file2ext "$fullfile" extension echo "$fullfile -> $filename . $extension" 

मैं निम्नलिखित स्क्रिप्ट का उपयोग करता हूँ

 $ echo "foo.tar.gz"|rev|cut -d"." -f3-|rev foo 
 $ F = "text file.test.txt" $ echo ${F/*./} txt 

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

स्वाभाविक रूप से यह विधि .tar.gz फ़ाइलों के लिए काम नहीं करती है। हालांकि यह दो चरण प्रक्रिया में नियंत्रित किया जा सकता है यदि एक्सटेंशन gz है तो फिर यह देखने के लिए जांचें कि क्या कोई भी टैरा एक्सटेंशन भी है।

मछली में फ़ाइल नाम और विस्तार कैसे निकालें:

 function split-filename-extension --description "Prints the filename and extension" for file in $argv if test -f $file set --local extension (echo $file | awk -F. '{print $NF}') set --local filename (basename $file .$extension) echo "$filename $extension" else echo "$file is not a valid file" end end end 

चेतावनियां: आखिरी डॉट पर विभाजन, जो उन फाइलों के लिए अच्छी तरह से काम करता है, जिनमें डॉट्स होते हैं, लेकिन उनमें डॉट्स के साथ विस्तार नहीं किया जाता है। नीचे उदाहरण देखें।

उपयोग:

 $ split-filename-extension foo-0.4.2.zip bar.tar.gz foo-0.4.2 zip # Looks good! bar.tar gz # Careful, you probably want .tar.gz as the extension. 

संभवत: ऐसा करने के लिए बेहतर तरीके हैं इसे सुधारने के लिए मेरे उत्तर को संपादित करने के लिए स्वतंत्र महसूस करें


यदि आप सीमित एक्सटेंशन का विस्तार कर रहे हैं तो आप उनसे निपटेंगे और आप उन सभी को जानते हैं, यह प्रयास करें:

 switch $file case *.tar echo (basename $file .tar) tar case *.tar.bz2 echo (basename $file .tar.bz2) tar.bz2 case *.tar.gz echo (basename $file .tar.gz) tar.gz # and so on end 

यह पहली उदाहरण के रूप में चेतावनी नहीं है, लेकिन आपको हर मामले को संभालना पड़ता है ताकि आप कितने एक्सटेंशन की उम्मीद कर सकते हैं, यह अधिक कठिन हो सकता है।

यहां एडब्ल्यूके के साथ कोड है इसे और अधिक आसानी से किया जा सकता है लेकिन मैं AWK में अच्छा नहीं हूँ।

 filename$ ls abc.a.txt abctxt pp-kk.txt filename$ find . -type f | awk -F/ '{print $2}' | rev | awk -F"." '{$1="";print}' | rev | awk 'gsub(" ",".") ,sub(".$", "")' abc.a abc pp-kk filename$ find . -type f | awk -F/ '{print $2}' | awk -F"." '{print $NF}' txt txt txt 

सबसे छोटा और सरल समाधान (एकल पंक्ति में) है:

$ file=/blaabla/bla/blah/foo.txt

echo $(basename ${file%.*})

foo

एक साधारण जवाब:

POSIX वैरिएबल के उत्तर पर विस्तार करने के लिए, ध्यान दें कि आप अधिक रोचक पैटर्न कर सकते हैं। इसलिए यहां बताई गई केस के लिए, आप बस ऐसा कर सकते हैं:

 tar -zxvf $1 cd ${1%.tar.*} 

यह .tar की आखिरी घटना को काट देगा <कुछ>

अधिक सामान्यतः, यदि आप अंतिम घटना को निकालना चाहते हैं तो <कुछ> <कुछ और तो > फिर

 ${1.*.*} 

ठीक काम करना चाहिए

ऊपर दिए गए उत्तर को मृत होना प्रतीत होता है। यहाँ स्ट्रिंग हेरफेर के एक गुच्छा का एक बड़ा स्पष्टीकरण है जिसे आप सीधे बाश में कर सकते हैं, टीएलडीपी से ।

पेटेस जवाब से भवन, अगर केवल फ़ाइल नाम की आवश्यकता है, तो दोनों रास्ते और विस्तार को एक पंक्ति में छीन लिया जा सकता है,

 filename=$(basename ${fullname%.*}) 

बड़े पैमाने पर @ एमकेलेमेंट 0 के उत्कृष्ट, और यादृच्छिक, उपयोगी संस्कारों के साथ-साथ अन्य / अन्य सवालों के जवाब के साथ-साथ "उस इंटरनेट पर झंझट " के आधार पर … मैं इसे थोड़ा-थोड़ा, अधिक सुगम, मेरे (या आपके) .bash_profile लिए पुन: प्रयोज्य फ़ंक्शन जो कि (मैं क्या विचार करता है) dirname / basename / आपके पास क्या एक अधिक मजबूत संस्करण होना चाहिए ..

 function path { SAVEIFS=$IFS; IFS="" # stash IFS for safe-keeping, etc. [[ $# != 2 ]] && echo "usage: path <path> <dir|name|fullname|ext>" && return # demand 2 arguments [[ $1 =~ ^(.*/)?(.+)?$ ]] && { # regex parse the path dir=${BASH_REMATCH[1]} file=${BASH_REMATCH[2]} ext=$([[ $file = *.* ]] && printf %s ${file##*.} || printf '') # edge cases for extesionless files and files like ".nesh_profile.coffee" [[ $file == $ext ]] && fnr=$file && ext='' || fnr=${file:0:$((${#file}-${#ext}))} case "$2" in dir) echo "${dir%/*}"; ;; name) echo "${fnr%.*}"; ;; fullname) echo "${fnr%.*}.$ext"; ;; ext) echo "$ext"; ;; esac } IFS=$SAVEIFS } 

Usage examples…

 SOMEPATH=/path/to.some/.random\ file.gzip path $SOMEPATH dir # /path/to.some path $SOMEPATH name # .random file path $SOMEPATH ext # gzip path $SOMEPATH fullname # .random file.gzip path gobbledygook # usage: -bash <path> <dir|name|fullname|ext> 

From the answers above, the shortest oneliner to mimic Python's

 file, ext = os.path.splitext(path) 

presuming your file really does have an extension, is

 EXT="${PATH##*.}"; FILE=$(basename "$PATH" .$EXT) 

If you also want to allow empty extensions, this is the shortest I could come up with:

 sed -r 's/.+\.(.+)|.*/\1/' # EXTENSION sed -r 's/(.+)\..+|(.*)/\1\2/' # FILENAME 

1st line explained: It matches PATH.EXT or ANYTHING and replaces it with EXT. If ANYTHING was matched, the ext group is not captured.

In order to make dir more useful (in the case a local file with no path is specified as input) I did the following:

 # Substring from 0 thru pos of filename dir="${fullpath:0:${#fullpath} - ${#filename}}" if [[ -z "$dir" ]]; then dir="./" fi 

This allows you to do something useful like add a suffix to the input file basename as:

 outfile=${dir}${base}_suffix.${ext} testcase: foo.bar dir: "./" base: "foo" ext: "bar" outfile: "./foo_suffix.bar" testcase: /home/me/foo.bar dir: "/home/me/" base: "foo" ext: "bar" outfile: "/home/me/foo_suffix.bar" 

आप उपयोग कर सकते हैं

 sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2- 

to get file name and

 sed 's/^/./' | rev | cut -d. -f1 | rev 

to get extension.

परीक्षण का मामला:

 echo "filename.gz" | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2- echo "filename.gz" | sed 's/^/./' | rev | cut -d. -f1 | rev echo "filename" | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2- echo "filename" | sed 's/^/./' | rev | cut -d. -f1 | rev echo "filename.tar.gz" | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2- echo "filename.tar.gz" | sed 's/^/./' | rev | cut -d. -f1 | rev 

Here is the algorithm I used for finding the name and extension of a file when I wrote a Bash script to make names unique when names conflicted with respect to casing.

 #! /bin/bash # # Finds # -- name and extension pairs # -- null extension when there isn't an extension. # -- Finds name of a hidden file without an extension # declare -a fileNames=( '.Montreal' '.Rome.txt' 'Loundon.txt' 'Paris' 'San Diego.txt' 'San Francisco' ) echo "Script ${0} finding name and extension pairs." echo for theFileName in "${fileNames[@]}" do echo "theFileName=${theFileName}" # Get the proposed name by chopping off the extension name="${theFileName%.*}" # get extension. Set to null when there isn't an extension # Thanks to mklement0 in a comment above. extension=$([[ "$theFileName" == *.* ]] && echo ".${theFileName##*.}" || echo '') # a hidden file without extenson? if [ "${theFileName}" = "${extension}" ] ; then # hidden file without extension. Fixup. name=${theFileName} extension="" fi echo " name=${name}" echo " extension=${extension}" done 

The test run.

 $ config/Name\&Extension.bash Script config/Name&Extension.bash finding name and extension pairs. theFileName=.Montreal name=.Montreal extension= theFileName=.Rome.txt name=.Rome extension=.txt theFileName=Loundon.txt name=Loundon extension=.txt theFileName=Paris name=Paris extension= theFileName=San Diego.txt name=San Diego extension=.txt theFileName=San Francisco name=San Francisco extension= $ 

FYI: The complete transliteration program and more test cases can be found here: https://www.dropbox.com/s/4c6m0f2e28a1vxf/avoid-clashes-code.zip?dl=0

Using example file /Users/Jonathan/Scripts/bash/MyScript.sh , this code:

 MY_EXT=".${0##*.}" ME=$(/usr/bin/basename "${0}" "${MY_EXT}") 

will result in ${ME} being MyScript and ${MY_EXT} being .sh :


स्क्रिप्ट:

 #!/bin/bash set -e MY_EXT=".${0##*.}" ME=$(/usr/bin/basename "${0}" "${MY_EXT}") echo "${ME} - ${MY_EXT}" 

Some tests:

 $ ./MyScript.sh MyScript - .sh $ bash MyScript.sh MyScript - .sh $ /Users/Jonathan/Scripts/bash/MyScript.sh MyScript - .sh $ bash /Users/Jonathan/Scripts/bash/MyScript.sh MyScript - .sh