2010-07-29 19 views
249

में किसी पथ से फ़ाइल नाम प्राप्त करें, मुझे विस्तार के बिना फ़ाइल नाम कैसे मिलेगा और कोई रास्ता नहीं होगा?बस बैश स्क्रिप्ट

निम्नलिखित मुझे कोई विस्तार देता है, लेकिन मैं अभी भी पथ संलग्न:

source_file_filename_no_ext=${source_file%.*} 
+2

'गूंज $ (basename" $ ​​{। Filepath% *} ")' – signal

उत्तर

461

अधिकांश यूनिक्स जैसे ऑपरेटिंग सिस्टम (पथ के लिए और dirname) एक बहुत ही इसी तरह के प्रयोजन के लिए एक basename निष्पादन योग्य है:

pax> a=/tmp/file.txt 
pax> b=$(basename $a) 
pax> echo $b 
file.txt 

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

तो, आपको वैसे भी ऐसा करना है, आपको एक विधि भी मिल सकती है जो पथ और एक्सटेंशन को बंद कर सकती है। ऐसा

एक तरह से करने के लिए (और यह है एक bash -only समाधान, कोई अन्य निष्पादनयोग्य की आवश्यकता होगी,): छोटा-सा स्निपेट सेट

pax> a=/tmp/xx/file.tar.gz 
pax> xpath=${a%/*} 
pax> xbase=${a##*/} 
pax> xfext=${xbase##*.} 
pax> xpref=${xbase%.*} 
pax> echo;echo path=${xpath};echo pref=${xpref};echo ext=${xfext} 

path=/tmp/xx 
pref=file.tar 
ext=gz 

कि xpath (फ़ाइल पथ), xpref (फ़ाइल उपसर्ग, क्या आप विशेष रूप से पूछ रहे थे) और xfext (फ़ाइल एक्सटेंशन)।

+0

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

+0

यदि आप पथ का उपयोग करना चाहते हैं: पथ = $ (echo $ filename | sed -e's/\/[^ \ /] * $/\ // ') यदि आप विस्तार प्राप्त करना चाहते हैं: ext = $ (echo $ filename | sed -e's /[^\.]*\.// ') – jcubic

+3

@ केथ: पथनाम के लिए, 'path = $ (dirname $ filename) का उपयोग करें; आपको प्रति एक्सटेंशन देने के लिए कोई आदेश नहीं है, लेकिन @ पक्सडीब्लो ने आपको दिखाया कि खोल कैसे कर सकता है। –

10
$ source_file_filename_no_ext=${source_file%.*} 
$ echo ${source_file_filename_no_ext##*/} 
+0

मुझे केवल एक मिलता है इसका उपयोग कर एक्सटेंशन के साथ वाइल्डकार्ड। – Kebman

18

यहाँ एक मार्ग से फ़ाइल नाम पाने के लिए एक आसान तरीका है:

echo "$PATH" | rev | cut -d"/" -f1 | rev 

विस्तार आप उपयोग कर सकते हैं निकालने के लिए, फ़ाइल नाम मानते हुए है केवल एक बिंदु (विस्तार डॉट):

cut -d"." -f1 
+7

यह एक अच्छी धारणा नहीं है, और टूल और कमांड विशिष्ट रूप से ऐसा करने के लिए डिज़ाइन किए गए हैं। – Tony

+0

इसके अतिरिक्त, मैं चर नाम 'PATH' का उपयोग करने की अनुशंसा नहीं करता, क्योंकि यह सिस्टम के' पथ 'चर – Tabea

19

basename और dirname समाधान अधिक सुविधाजनक हैं।

FILE_PATH="/opt/datastores/sda2/test.old.img" 
echo "$FILE_PATH" | sed "s/.*\///" 

यह test.old.imgbasename की तरह रिटर्न: उन वैकल्पिक आदेशों हैं।

इस विस्तार के बिना नमक फ़ाइल नाम है:

echo "$FILE_PATH" | sed -r "s/.+\/(.+)\..+/\1/" 

यह रिटर्न test.old

और निम्नलिखित कथन dirname कमांड जैसे पूर्ण पथ देता है।

echo "$FILE_PATH" | sed -r "s/(.+)\/.+/\1/" 

यह /opt/datastores/sda2

+0

कूल के साथ संघर्ष कर सकता है, यदि पैरामीटर हैं तो क्या होगा? –

6

कुछ और वैकल्पिक विकल्पों रिटर्न क्योंकि regexes (regi?) भयानक कर रहे हैं!

regex="[^/]*$" 

उदाहरण (ग्रेप):

FP="/hello/world/my/file/path/hello_my_filename.log" 
echo $FP | grep -oP "$regex" 
#Or using standard input 
grep -oP "$regex" <<< $FP 

उदाहरण (awk):

echo $FP | awk '{match($1, "$regex",a)}END{print a[0]} 
#Or using stardard input 
awk '{match($1, "$regex",a)}END{print a[0]} <<< $FP 

यहाँ काम करने के लिए एक सरल regex है

यदि आपको अधिक जटिल रेगेक्स की आवश्यकता है: उदाहरण के लिए आपका पथ स्ट्रिंग में लपेटा गया है।

StrFP="my string is awesome file: /hello/world/my/file/path/hello_my_filename.log sweet path bro." 

#this regex matches a string not containing/and ends with a period 
#then at least one word character 
#so its useful if you have an extension 

regex="[^/]*\.\w{1,}" 

#usage 
grep -oP "$regex" <<< $StrFP 

#alternatively you can get a little more complicated and use lookarounds 
#this regex matches a part of a string that starts with/that does not contain a/
##then uses the lazy operator ? to match any character at any amount (as little as possible hence the lazy) 
##that is followed by a space 
##this allows use to match just a file name in a string with a file path if it has an exntension or not 
##also if the path doesnt have file it will match the last directory in the file path 
##however this will break if the file path has a space in it. 

regex="(?<=/)[^/]*?(?=\s)" 

#to fix the above problem you can use sed to remove spaces from the file path only 
## as a side note unfortunately sed has limited regex capibility and it must be written out in long hand. 
NewStrFP=$(echo $StrFP | sed 's:\(/[a-z]*\)\(\)\([a-z]*/\):\1\3:g') 
grep -oP "$regex" <<< $NewStrFP 

regexes के साथ कुल समाधान:

इस समारोह के साथ या एक linux filepath फ़ाइल नाम कई है, भले ही के विस्तार के बिना आप फ़ाइल नाम दे सकते हैं उस में s "।"। यह फ़ाइलपैथ में रिक्त स्थान भी संभाल सकता है और यदि फ़ाइल पथ एक स्ट्रिंग में एम्बेडेड या लपेटा गया है।

#you may notice that the sed replace has gotten really crazy looking 
#I just added all of the allowed characters in a linux file path 
function Get-FileName(){ 
    local FileString="$1" 
    local NoExtension="$2" 
    local FileString=$(echo $FileString | sed 's:\(/[a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*\)\(\)\([a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*/\):\1\3:g') 

    local regex="(?<=/)[^/]*?(?=\s)" 

    local FileName=$(echo $FileString | grep -oP "$regex") 

    if [[ "$NoExtension" != "" ]]; then 
     sed 's:\.[^\.]*$::g' <<< $FileName 
    else 
     echo "$FileName" 
    fi 
} 

## call the function with extension 
Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." 

##call function without extension 
Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." "1" 

आप इस एक के साथ शुरू कर सकते हैं यदि आप एक विंडोज़ पथ के साथ गड़बड़ करने के लिए है, तो:

[^\\]*$  
5
$ file=${$(basename $file_path)%.*} 
+0

यह बैश v4.4.7 में "खराब प्रतिस्थापन" देता है। मुझे लगता है कि फ़ित्र कुकुक के sed समाधान बेहतर है, यानी $ (बेसनाम $ the_file_path) | sed "s /\..*//" – Marshal

+0

मेरा मतलब था 'echo $ (बेसनाम $ the_file_path) | sed "s /\..*//" ' – Marshal

संबंधित मुद्दे