බාෂ් හි ගොනු නාමය සහ දිගුව උපුටා ගන්න


2122

ගොනු නාමය (දිගුවකින් තොරව) සහ දිගුව වෙන වෙනම ලබා ගැනීමට මට අවශ්‍යය.

මම මෙතෙක් සොයාගත් හොඳම විසඳුම නම්:

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

මෙය වැරදියි, මන්ද ගොනුවේ නමේ .අක්ෂර කිහිපයක් තිබේ නම් එය ක්‍රියා නොකරයි . මා සතුව තිබේ නම් a.b.js, එය සලකා බලනු ඇති aඅතර b.js, ඒ වෙනුවට a.bසහ js.

එය පහසුවෙන් පයිතන් සමඟ කළ හැකිය

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

නමුත් මම කැමතියි හැකි නම් මේ සඳහා පයිතන් පරිවර්තකයෙකුට වෙඩි නොතබන්න.

වඩා හොඳ අදහස් තිබේද?


මෙම ප්රශ්නය මෙම bash තාක්ෂණය සහ තවත් අදාළ කිහිපයක් පැහැදිලි කරයි.
jjclarkson

28
පහත දැක්වෙන විශිෂ්ට පිළිතුරු යොදන විට, මම මෙහි පෙන්වා ඇති ආකාරයට ඔබේ විචල්‍යය තුළ අලවන්න එපා වැරදියි: extension="{$filename##*.}" මම ටික කලක් කළාක් මෙන්! $කරකැවිල්ලෙන් පිටතට ගෙනයන්න : දකුණ: extension="${filename##*.}"
ක්‍රිස් කේ

4
මෙය පැහැදිලිවම සුළුපටු නොවන ගැටළුවක් වන අතර පහත පිළිතුරු සම්පූර්ණයෙන්ම නිවැරදි දැයි මට කීමට අපහසුය. මෙය පුදුම සහගතය (බා) ෂා හි ක්‍රියාත්මක වූ ක්‍රියාවලියක් නොවේ (පිළිතුරු රටා ගැලපීම භාවිතයෙන් ක්‍රියාව ක්‍රියාත්මක කරන බව පෙනේ). මම os.path.splitextඒ වෙනුවට පයිතන් භාවිතා කිරීමට තීරණය කළෙමි ...
පීටර් ගිබ්සන්

1
ලෙස දීර්ඝ නියෝජනය කිරීමට ඇති ස්වභාවය ගොනු වන, පවතින මැජික් වන චෙක්පත ගොනුව ඔහුගේ ස්වභාවය දිව්යමය හා offert කිරීමට අණ සම්මත දීර්ඝ . මගේ පිළිතුර
එෆ්. හවුරි

2
ප්‍රශ්නය මුලින් ම ගැටළු සහගත වන්නේ මෙහෙයුම් පද්ධතියේ සහ යුනික්ස් ගොනු පද්ධතිවල දෘෂ්ටි කෝණයෙන් බලන කල, ගොනු දිගුවක් වැනි දෙයක් නොමැති බැවිනි. "." කොටස් වෙන් කිරීම මානව සම්මුතියක් වන අතර එය ක්‍රියාත්මක වන්නේ මිනිසුන් එය අනුගමනය කිරීමට එකඟ වන තාක් කල් පමණි. උදාහරණයක් ලෙස, 'තාර' වැඩසටහන සමඟ, නිමැවුම් ලිපිගොනු "තාර" ලෙස නම් කිරීමට තීරණය කළ හැකිය. ".tar" උපසර්ගය වෙනුවට උපසර්ගය - "somedir.tar" වෙනුවට "tar.somedir" ලබා දීම. මේ නිසා "සාමාන්‍ය, සැමවිටම ක්‍රියා කරන" විසඳුමක් නොමැත - ඔබේ විශේෂිත අවශ්‍යතා හා අපේක්ෂිත ගොනු නාමයන්ට ගැලපෙන කේතයක් ලිවිය යුතුය.
සීඑම්

Answers:


3528

පළමුව, මාර්ගය නොමැතිව ගොනු නාමය ලබා ගන්න:

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

විකල්පයක් ලෙස, ඔබට '' වෙනුවට මාර්ගයේ අවසාන '/' වෙත අවධානය යොමු කළ හැකිය. ඔබට අනපේක්ෂිත ගොනු දිගු තිබුණත් එය ක්‍රියාත්මක විය යුතුය:

filename="${fullfile##*/}"

ඔබට ප්‍රලේඛනය පරීක්ෂා කිරීමට අවශ්‍ය විය හැකිය:


85
සම්පූර්ණ විශේෂාංග කට්ටලය සඳහා gnu.org/software/bash/manual/html_node/… බලන්න .
ඩී. ෂව්ලි

24
"$ Fullfile" වෙත උපුටා දැක්වීම් කිහිපයක් එක් කරන්න, නැතහොත් ගොනු නාමය බිඳ දැමීමේ අවදානමක් ඇත.
lhunath

47
ක්රිටයා, ඔබ වැඩිපුර ඇමතුම් පවා කපා ගොනු = "$ {## fullfile * /}" හා වැලැක්විමට හැකිbasename
ephemient

45
ගොනුවට දිගුවක් නොමැති නම් මෙම "විසඳුම" ක්‍රියා නොකරයි - ඒ වෙනුවට, සම්පූර්ණ ගොනුවේ නම ප්‍රතිදානය වන අතර, දිගු නොමැතිව ලිපිගොනු සර්වප්‍රකාරයෙන් සලකන විට එය තරමක් නරක ය.
nccc

43
දිගුවකින් තොරව ගොනු නාම සමඟ කටයුතු කිරීම සඳහා නිවැරදි කරන්න : extension=$([[ "$filename" = *.* ]] && echo ".${filename##*.}" || echo ''). දිගුවක් තිබේ නම් , එය ආරම්භක ., උදා .txt.
mklement0

692
~% FILE="example.tar.gz"

~% echo "${FILE%%.*}"
example

~% echo "${FILE%.*}"
example.tar

~% echo "${FILE#*.}"
tar.gz

~% echo "${FILE##*.}"
gz

වැඩි විස්තර සඳහා, Bash අත්පොතේ ෂෙල් පරාමිති පුළුල් කිරීම බලන්න .


22
.Tar.gz හි මෙන්, ගොනු නාමයේ "දිගුව" කොටසෙහි තිත් 2 ක් තිබේ නම් කුමක් කළ යුතුද යන විශිෂ්ට ප්‍රශ්නය ඔබ (සමහර විට නොදැනුවත්වම) මතු කරයි ... මම කිසි විටෙකත් එම ප්‍රශ්නය සලකා බැලුවේ නැත, එය සැක කරමි හැකි සෑම වලංගු ගොනු දිගුවක්ම නොදැන විසඳිය නොහැක.
rmeador

8
විසඳිය නොහැක්කේ ඇයි? මගේ උදාහරණයේ දී, ගොනුවේ දිගුවන් දෙකක් ඇති බව සැලකිය යුතුය, තිත් දෙකක් සහිත දිගුවක් නොවේ. ඔබ දිගු දෙකම වෙන වෙනම හසුරුවයි.
ජූලියානෝ

22
එය ශබ්දකෝෂ පදනමක් මත විසඳිය නොහැකි ය, ඔබට ගොනු වර්ගය පරීක්ෂා කිරීමට අවශ්‍ය වේ. ඔබ කැඳවා ක්රීඩාවක් තිබුණා නම් සලකා බලන්න dinosaurs.in.tarඔබට එය gzipped dinosaurs.in.tar.gz:)
porges

11
ඔබ සම්පූර්ණ මාවත්වල ගමන් කරන්නේ නම් මෙය වඩාත් සංකීර්ණ වේ. මගේ එක් අයෙකුට '.' මාර්ගය මැද ඇති නාමාවලියක, නමුත් ගොනු නාමයේ කිසිවක් නැත. උදාහරණය "a / bc / d / e / filename" අවසන් වනු ඇත ".c / d / e / filename"
වෝල්ට් සෙලර්ස්

7
පැහැදිලිවම x.tar.gzදිගුවක් නොමැති gzඅතර ගොනු නාමය එයයි x.tar. ද්විත්ව දිගු වැනි දෙයක් නොමැත. මට විශ්වාසයි බූස්ට් :: ගොනු පද්ධතිය එය ඒ ආකාරයෙන් හසුරුවයි. (බෙදීම් මාර්ගය, change_extension ...) සහ එහි හැසිරීම පදනම් වී ඇත්තේ මා වරදවා වටහා නොගන්නේ නම් පයිතන් මත ය.
v.oddou

434

සාමාන්‍යයෙන් ඔබ දිගුව දැනටමත් දන්නා බැවින් ඔබට භාවිතා කිරීමට අවශ්‍ය විය හැකිය:

basename filename .extension

උදාහරණයක් වශයෙන්:

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

අපිට ලැබෙනවා

filename

62
ඒ දෙවන තර්කය basenameඇස්
ඇරීම

10
මෙම තාක්ෂණය භාවිතා කරමින් දිගුව උපුටා ගන්නේ කෙසේද? ;) ඔහ්, ඉන්න! අපි එය කලින් දන්නේ නැහැ.
ටොමාස් ගන්ඩෝර්

3
සමග අවසන් එක්කෝ ඔබ සිප් බහලුම සතුව කියන්න .zipහෝ .ZIP. ඔබට එවැනි දෙයක් කළ හැකි ක්‍රමයක් basename $file {.zip,.ZIP}තිබේද?
ඩෙනිස්

8
මෙය OPs ප්‍රශ්නයේ කොටසක් පමණක් පිළිතුරු සපයන අතර, එය මම ගූගල් වෙත ටයිප් කළ ප්‍රශ්නයට පිළිතුරු සපයයි. :-) හරිම සිනිඳුයි!
sudo make install

1
පහසු සහ POSIX අනුකූල
gpanda

147

ඔබට 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

5
ජොකිම්ගේ පිළිතුරට වඩා බොහෝ සරල නමුත් මට සෑම විටම POSIX විචල්‍ය ආදේශනය සොයා බැලිය යුතුය. එසේම, මෙම මැක්ස් OSX එකක් එහිදී මත ධාවනය cutනැත --complementහා sedනැති -r.
jwadsack

72

ගොනුවට දිගුවක් හෝ ගොනු නාමයක් නොමැති නම් එය ක්‍රියා කරන බවක් නොපෙනේ. මෙන්න මම භාවිතා කරන්නේ; එය බිල්ඩින් පමණක් භාවිතා කරන අතර වැඩි (නමුත් සියල්ලම නොවේ) ව්යාධිජනක ගොනු නාමයන් හසුරුවයි.

#!/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-and-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 = "/"
    base = ""
    ext = ""
/ home / me /:
    dir = "/ home / me /"
    base = ""
    ext = ""
/ home / me / file:
    dir = "/ home / me /"
    base = "ගොනුව"
    ext = ""
/home/me/file.tar:
    dir = "/ home / me /"
    base = "ගොනුව"
    ext = "තාර"
/home/me/file.tar.gz:
    dir = "/ home / me /"
    base = "file.tar"
    ext = "gz"
/home/me/.hidden:
    dir = "/ home / me /"
    base = ".hidden"
    ext = ""
/home/me/.hidden.tar:
    dir = "/ home / me /"
    base = ".hidden"
    ext = "තාර"
/ home / me / ..:
    dir = "/ home / me /"
    base = ".."
    ext = ""
.:
    dir = ""
    base = "."
    ext = ""

2
ඒ වෙනුවට dir="${fullpath:0:${#fullpath} - ${#filename}}"මම බොහෝ විට දැක ඇත්තෙමි dir="${fullpath%$filename}". එය ලිවීම සරල ය. සැබෑ වේග වෙනසක් හෝ ගොචා තිබේදැයි විශ්වාස නැත.
dubiousjim

2
මෙය #! / Bin / bash භාවිතා කරන අතර එය සෑම විටම පාහේ වැරදිය. හැකි නම් #! / Bin / sh හෝ #! / Usr / bin / env bash නැතිනම් කැමති වන්න.
හොඳ පුද්ගලයා

Ood හොඳ පුද්ගලයා: එය සෑම විටම පාහේ වැරදි වන්නේ කෙසේදැයි මම නොදනිමි: which bash-> /bin/bash; සමහර විට එය ඔබේ ඩිස්ට්‍රෝ ද?
vol7ron

2
@ vol7ron - බොහෝ ඩිස්ට්‍රෝස් බැෂ් / usr / local / bin / bash හි ඇත. OSX හි බොහෝ අය යාවත්කාලීන කළ බැෂ් එකක් / opt / local / bin / bash හි ස්ථාපනය කරති. එනිසා / බින් / බාෂ් වැරදියි, එය සොයා ගැනීමට යමෙක් env භාවිතා කළ යුතුය. ඊටත් වඩා හොඳ වන්නේ / bin / sh සහ POSIX ඉදිකිරීම් භාවිතා කිරීමයි. සූර්ය බලශක්තිය හැරුණු විට මෙය පොසික්ස් කවචයකි.
හොඳ පුද්ගලයා

2
Ood ගුඩ්පර්සන් නමුත් ඔබ බාෂ් සමඟ වඩාත් සැපපහසු නම්, sh භාවිතා කරන්නේ ඇයි? එය sh වැනි දෙයක් නොවේද, ඔබට sh භාවිතා කළ හැකි විට පර්ල් භාවිතා කරන්නේ ඇයි?
vol7ron

46

ඔබට භාවිතා කළ හැකිය basename.

උදාහරණයක්:

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

ඉවත් කළ යුතු දිගුව සමඟ ඔබට මූලික නම ලබා දිය යුතුය, කෙසේ වෙතත් ඔබ සැමවිටම ක්‍රියාත්මක tarකරන්නේ -zනම් දිගුව වනු ඇති බව ඔබ දනී .tar.gz.

මෙය ඔබට අවශ්‍ය දේ කළ යුතුය:

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

2
cd $(basename $1 .tar.gz).Gz ගොනු සඳහා වැඩ කරයි යැයි සිතමි . නමුත් ඔහු සඳහන් කළ ප්‍රශ්නයArchive files have several extensions: tar.gz, tat.xz, tar.bz2
එස්එස් හෙග්ඩේ

ටොමී පෝ මීට වසර 2 කට පෙර එම දේම පළ කළේය.
phil294

හායි බ්ලූහර්න්, වාව් මේක පරණ ප්‍රශ්නයක්. මම හිතන්නේ දින වකවානු වලට යමක් සිදුවී ඇත. මට ප්‍රශ්නයක් ඇසූ සැණින් පිළිතුරු දුන් බව මට මතකයි. එහිදී තවත් පිළිතුරු කිහිපයක් පමණි. ප්‍රශ්නය වෙනත් ප්‍රශ්නයක් සමඟ ඒකාබද්ධ වී තිබේද? SO එසේ කරයිද?
බාර්ක් ෆ්‍රවුන්ඩ්-හැන්සන්

ඔව් මට නිවැරදිව මතකයි. මම මුලින් මෙම ප්‍රශ්නයට පිළිතුරු සපයන්නේ stackoverflow.com/questions/14703318/… එය ඇසූ දිනයේම, වසර 2 කට පසුව එය මෙම ප්‍රශ්නයට ඒකාබද්ධ කරන ලදි. මගේ පිළිතුර මේ ආකාරයෙන් ගෙන යන විට අනුපිටපත් පිළිතුරකට මට දොස් පැවරිය නොහැකිය.
Bjarke Freund-Hansen

38
pax> echo a.b.js | sed 's/\.[^.]*$//'
a.b
pax> echo a.b.js | sed 's/^.*\.//'
js

හොඳින් ක්‍රියා කරයි, එවිට ඔබට භාවිතා කළ හැකිය:

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

විධාන, මාර්ගය වන විට, පහත පරිදි ක්රියා කරයි.

පේළියේ අවසානය දක්වා අක්ෂර නොවන ඕනෑම සංඛ්‍යාවක් අනුගමනය කරන අක්‍ෂරයක් NAMEආදේශ කිරීම සඳහා වන විධානය , කිසිවක් නොමැතිව (එනම්, එය අවසන් සිට පේළියේ අවසානය දක්වා සියල්ල ඉවත් කරයි ). මෙය මූලික වශයෙන් රිජෙක්ස් උපක්‍රම භාවිතා කරමින් කෑදර නොවන ආදේශකයකි."."".""."

පේළියේ ආරම්භයේ දී EXTENSIONඅක්ෂරයකින් පසුව ඕනෑම අක්ෂර සංඛ්‍යාවක් ආදේශ කිරීම සඳහා වන විධානය ".", කිසිවක් නොමැතිව (එනම්, එය රේඛාවේ ආරම්භයේ සිට අවසාන තිත දක්වා සියල්ල ඉවත් කරයි). මෙය ගිජු ආදේශනයකි.


දිගුවකින් තොරව ලිපිගොනු සඳහා මෙම බිඳීම නම සහ දිගුව සඳහා මුද්‍රණය කරයි. එබැවින් මම sed 's,\.[^\.]*$,,'නම සහ sed 's,.*\.,., ;t ;g'දීර් extension කිරීම සඳහා භාවිතා කරමි ( සාමාන්‍ය විධානය සමඟ පරස්පර testසහ getවිධාන භාවිතා කරයි substitute).
hIpPy

32

බ්ලොග් සටහනක් ගැන අදහස් දක්වමින් මෙලන් මෙසේ ලියයි:

Bash භාවිතා කරමින්, ${file%.*}දිගුවකින් තොරව ගොනු නාමය ${file##*.}ලබා ගැනීමට සහ දිගුව තනිවම ලබා ගැනීමටද ඇත. එනම්,

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

නිමැවුම්:

filename: thisfile
extension: txt


29

කරදර වෙන්න අවශ්ය නෑ awkහෝ sedපවා perlමෙම සරල කාර්යය සඳහා. os.path.splitext()පරාමිති පුළුල් කිරීම් පමණක් භාවිතා කරන පිරිසිදු-බෑෂ්, අනුකූල විසඳුමක් ඇත.

යොමු ක්‍රියාත්මක කිරීම

ප්‍රලේඛනය os.path.splitext(path):

යුගලයක් බවට pathname මාර්ගය බෙදී (root, ext), එවන් root + ext == path, සහ ඔබ මෙතෙක් හිස් හෝ කාලය ආරම්භ වීමත් සමග බොහෝ එක් කාල දී අඩංගු වේ. මූලික නාමයේ ප්‍රමුඛ කාල පරිච්ඡේද නොසලකා හරිනු ලැබේ; 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' |
|---------------|-----------|-------|

පරීක්ෂණ ප්‍රති .ල

සියලුම පරීක්ෂණ සමත් විය.


2
නැත, සඳහා මූලික ගොනුවේ නම text.tar.gzවිය යුතු textඅතර දිගුව විය යුතුය.tar.gz
frederick99

2
said frederick99 මා පැවසූ පරිදි මෙහි විසඳුම os.path.splitextපයිතන් ක්‍රියාත්මක කිරීමට ගැලපේ . මතභේදාත්මක යෙදවුම් සඳහා එය ක්‍රියාත්මක කිරීම සුදුසු ද යන්න තවත් මාතෘකාවකි.
සයිකර්

රටාව ( "$root") තුළ ඇති මිල ගණන් ක්‍රියාත්මක වන්නේ කෙසේද? ඒවා මඟ හැරියහොත් කුමක් සිදුවිය හැකිද? (මට මේ සම්බන්ධයෙන් කිසිදු ලේඛනයක් සොයාගත නොහැකි විය.) එසේම මෙම ලිපිගොනු ඒවා සමඟ *හෝ ?ඒවා සමඟ කටයුතු කරන්නේ කෙසේද?
ymett

හරි, මේ ආකාරයටම රටාව ප්රායෝගික, එනම් කරන්න මට දර්ශන පරීක්ෂා *හා ?විශේෂ නැහැ. ඉතින් මගේ ප්‍රශ්නයේ කොටස් දෙක එකිනෙකාට පිළිතුරු දෙයි. මෙය ලේඛනගත කර නොමැති බව මා නිවැරදිද? නැතහොත් උපුටා දැක්වීම් පොදුවේ ගෝලීය ව්‍යාප්තිය අක්‍රීය කරන බව තේරුම් ගත යුතුද?
ymett

දීප්තිමත් පිළිතුර! මූල ගණනය කිරීම සඳහා මම තරමක් සරල ප්‍රභේදයක් යෝජනා කරමි: root="${path#?}";root="${path::1}${root%.*}"- ඉන්පසු දිගුව උපුටා ගැනීම සඳහා ඉදිරියට යන්න.
Maëlan

26

cutඅවසාන දිගු දෙක ( ".tar.gz"කොටස) ඉවත් කිරීමට ඔබට විධානය භාවිතා කළ හැකිය :

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

සටහනක ක්ලේටන් හියුස් සඳහන් කළ පරිදි, මෙය ප්‍රශ්නයේ සත්‍ය උදාහරණය සඳහා ක්‍රියා නොකරනු ඇත. එබැවින් විකල්පයක් ලෙස මම යෝජනා කරන්නේ මේ ආකාරයට sedදීර් regular නිත්‍ය ප්‍රකාශන භාවිතා කිරීමට ය :

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

එය ක්‍රියාත්මක වන්නේ අවසාන (ඇල්ෆා-සංඛ්‍යාත්මක) දිගු දෙක කොන්දේසි විරහිතව ඉවත් කිරීමෙනි.

[ඇන්ඩර්ස් ලින්ඩාල්ගේ අදහස් දැක්වීමෙන් පසුව නැවත යාවත්කාලීන කරන ලදි]


4
මෙය ක්‍රියාත්මක වන්නේ ගොනු නාමය / මාර්ගයෙහි වෙනත් තිත් නොමැති අවස්ථාවක පමණි: echo "mpc-1.0.1.tar.gz" | cut -d '.' --complement -f2- "mpc-1" නිපදවයි (සීමා කිරීමෙන් පසු පළමු ක්ෂේත්‍ර දෙක පමණි.)
ක්ලේටන් හියුස්

La ක්ලේටන් හියුස් ඔබ නිවැරදියි, මම එය වඩා හොඳින් පරීක්ෂා කළ යුතුව තිබුණි. තවත් විසඳුමක් එක් කළේය.
සමහර ක්‍රමලේඛ මචන්

$ගැලපෙන දිගුව ගොනු නාමයේ අවසානයේ තිබේදැයි පරීක්ෂා කිරීමට sed ප්‍රකාශන භාවිතා කළ යුතුය . එසේ නොමැතිනම්, ගොනු නාමයක් වැනි i.like.tar.gz.files.tar.bz2අනපේක්ෂිත ප්‍රති .ල ලබා දිය හැකිය.
ඇන්ඩර්ස් ලින්ඩාල්

EndAndersLindahl දිගු වල sedඅනුපිළිවෙල දාම අනුපිළිවෙලෙහි ප්‍රතිලෝම නම් එය තවමත් සිදුවනු ඇත . පවා $අවසන් වන විට එවැනි ගොනු mpc-1.0.1.tar.bz2.tar.gzදෙකම ඉවත් කරනු ඇත .tar.gzඑදා සහ .tar.bz2.
සමහර ක්‍රමලේඛ මචන්

$ echo "foo.tar.gz" | cut -d '.' -f2- රහිතව - සම්පුර්ණ කිරීම මඟින් 2 වන බෙදීම් අයිතමය නූල් අවසානය දක්වා ලැබෙනු ඇත $ echo "foo.tar.gz" | cut -d '.' -f2- tar.gz
ජීන් බ්ලැක්

23

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 '^[/]\|^~/'

සියලු භාවිත අවස්ථා අතරමැදි ප්‍රති .ල මත පදනම්ව මුල් සම්පූර්ණ මාර්ගය ආදානය ලෙස භාවිතා කරයි.


21

මෙම පිළිගත් පිළිතුර දී හොඳින් ක්රියා සාමාන්ය නඩු , නමුත් අසාර්ථක අද්දර නඩු එනම්,:

  • දිගුවකින් තොරව ගොනු නාම සඳහා ( මෙම පිළිතුරේ ඉතිරි කොටසෙහි උපසර්ගය ලෙස හැඳින්වේ ), 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

19

කුඩාම හා සරලම විසඳුම (තනි පේළියේ):

$ file=/blaabla/bla/blah/foo.txt
echo $(basename ${file%.*}) # foo

එය නිෂ් less ල භාවිතයකිecho . පොදුවේ ගත් කල, echo $(command)වඩා හොඳින් ලියා ඇත්තේ commandප්‍රති the ලය commandපෙන්වීමට පෙර සිට නිමැවුමේ සුදු පැහැති ටෝකනකරණය සහ ආදේශක පුළුල් කිරීම සිදු කිරීමට ඔබට කවචයට අවශ්‍ය නොවන්නේ නම් පමණි . ප්‍රශ්නාවලිය: එහි ප්‍රති output ලය කුමක්ද echo $(echo '*')(ඔබට එය ඇත්තටම අවශ්‍ය නම්, ඔබට සැබවින්ම අවශ්‍ය වන්නේ සාධාරණයි echo *).
ත්‍රිත්ව

ripriplee මම කිසිසේත් echoවිධානය භාවිතා කළේ නැත . foo3 වන පේළියේ 2 වන පේළියේ ප්‍රති result ලය ලෙස පෙනෙන ප්‍රති result ලය නිරූපණය කිරීමට මම එය භාවිතා කළෙමි .
රොන්

නමුත් එය එසේම basename "${file%.*}"කරනු ඇත; ඔබ එහි ප්‍රතිදානය ග්‍රහණය කර ගැනීමට විධාන ආදේශකයක් භාවිතා කරයි, echoඑම නිමැවුමට වහාම. (උපුටා දැක්වීමකින් තොරව,
ප්‍රති result ලය

basename "$file" .txtපරාමිති ආදේශනයේ සංකීර්ණතාව ද වළක්වයි.
ත්‍රිත්ව

1
On රොන් අපේ කාලය නාස්ති කළ බවට චෝදනා කිරීමට පෙර ඔහුගේ පළමු අදහස කියවන්න.
frederick99

14

මම හිතන්නේ ඔබට ගොනුවේ නම අවශ්‍ය නම් ඔබට මෙය උත්සාහ කළ හැකිය:

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"

ඒ සියල්ල = ඩී.


අවශ්‍ය වූයේ BASEDIRECTORY :) ස්තූතියි!
කාලෝස් රිකාඩෝ

12

සියලුම ක්ෂේත්‍ර පෙන්වීමට ඔබට කප්පාදුව බල කළ හැකි අතර පසුව ඒවා -ක්ෂේත්‍ර අංකයට එකතු වේ.

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

එබැවින් FILE නම් eth0.pcap.gz, ව්‍යාප්තිය වනු ඇතpcap.gz

එකම තර්කනය භාවිතා කරමින්, ඔබට පහත පරිදි කප්පාදුවෙන් '-' භාවිතා කර ගොනු නාමය ලබා ගත හැකිය:

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

කිසිදු දිගුවක් නොමැති ගොනු නාම සඳහා පවා මෙය ක්‍රියා කරයි.


8

මැජික් ගොනු හඳුනාගැනීම

මෙම සිරස් පිටාර ගැලීමේ ප්‍රශ්නයට හොඳ පිළිතුරු රාශියකට අමතරව මම එකතු කිරීමට කැමතියි:

ලිනක්ස් සහ වෙනත් යුනික්සෙන් යටතේ, මැජික් විධානයක් නම් කර ඇත 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

ඔබට a නිර්මාණය කළ හැකිය නිවැරදි දිගුව තීරණය කිරීමේ කාර්යය. කුඩා (පරිපූර්ණ නොවේ) නියැදියක් ඇත:

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##*[/.-]}
}

මෙම ශ්‍රිතයට පසුව භාවිතා කළ හැකි Bash විචල්‍යයක් සැකසිය හැකිය:

(මෙය දේවානුභාවයෙන් @Petesh නිවැරදි පිළිතුරෙන්):

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

echo "$fullfile -> $filename . $extension"

8

හරි, මම නිවැරදිව තේරුම් ගත්තා නම්, මෙහි ඇති ගැටළුව වන්නේ බහු දිගුවන් ඇති ගොනුවක නම සහ සම්පූර්ණ දිගුව ලබා ගන්නේ කෙසේද යන්නයි stuff.tar.gz.

මෙය මට වැඩ කරයි:

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

මෙය ඔබට stuffගොනු නාමයක් .tar.gzලෙස සහ දිගුවක් ලෙස ලබා දෙනු ඇත . 0 ද ඇතුළුව ඕනෑම දිගු ගණනකට එය ක්‍රියා කරයි. එකම ගැටළුවක් ඇති ඕනෑම කෙනෙකුට මෙය උපකාරී වේ යැයි සිතමු =)


නිවැරදි ප්‍රති result ලය (අනුව os.path.splitext, OP ට අවශ්‍ය වන්නේ එයයි) ('stuff.tar', '.gz').
සයිකර්

6

මම පහත පිටපත භාවිතා කරමි

$ echo "foo.tar.gz"|rev|cut -d"." -f3-|rev
foo

මෙය කිසිසේත්ම කාර්යක්ෂම නොවේ. බාහිර විධානයන් සහ බලහත්කාරයෙන් තොරව මෙම ක්‍රියාව පිරිසිදු බාෂ් තුළ සිදු කළ හැකි බැවින් බොහෝ වාර ගණනක් දෙබලක යෙදීම.
codeforester

5
$ F = "text file.test.txt"  
$ echo ${F/*./}  
txt  

මෙය ගොනු නාමයක බහු තිත් සහ අවකාශයන් සපුරාලයි, කෙසේ වෙතත් දිගුවක් නොමැති නම් එය ගොනු නාමය නැවත ලබා දෙයි. කෙසේ වෙතත් පරීක්ෂා කිරීම පහසුය; ගොනු නාමය සහ දිගුව එකම දැයි පරීක්ෂා කරන්න.

ස්වාභාවිකවම මෙම ක්‍රමය .tar.gz ගොනු සඳහා ක්‍රියා නොකරයි. කෙසේ වෙතත් එය පියවර දෙකක ක්‍රියාවලියකින් හැසිරවිය හැකිය. දිගුව gz නම් තාර දිගුවක් ද තිබේදැයි බැලීමට නැවත පරීක්ෂා කරන්න.


5

මාළු වල ගොනු නාමය සහ දිගුව උකහා ගන්නේ කෙසේද :

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

Caveats: අන්තිම තිතෙහි බෙදීම්, ඒවා තුළ තිත් සහිත ගොනු නාම සඳහා හොඳින් ක්‍රියා කරයි, නමුත් ඒවායේ තිත් සහිත දිගු සඳහා එය හොඳ නැත. පහත උදාහරණය බලන්න.

භාවිතය:

$ 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

මෙය පළමු උදාහරණය ලෙස අවවාදයක් නොමැත , නමුත් ඔබට සෑම නඩුවක්ම හැසිරවිය යුතු අතර එමඟින් ඔබට අපේක්ෂා කළ හැකි දිගු ගණන මත පදනම්ව එය වඩාත් වෙහෙසකාරී විය හැකිය.


4

මෙන්න AWK සමඟ කේතය . එය වඩාත් සරලව කළ හැකිය. නමුත් මම AWK හි හොඳ නැත.

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

අන්තිම උදාහරණයේ පළමු අමුතු ප්‍රකාශය ඔබට අවශ්‍ය නොවිය යුතුය, නේද?
BHSPitMonkey

තවත් දෙයක් කිරීමෙන් ඔබට අව්ක් වෙත අවහිර කිරීම වළක්වා ගත හැකිය split(). awk -F / '{ n=split($2, a, "."); print a[n] }' uses / `ඉහළ මට්ටමේ පරිසීමකය ලෙස, නමුත් දෙවන ක්ෂේත්‍රයන් බෙදී .නව අරාවෙහි අවසාන අංගය මුද්‍රණය කරයි.
ත්‍රිත්ව

4

සරලව භාවිතා කරන්න ${parameter%word}

ඔබේ නඩුවේ:

${FILE%.*}

ඔබට එය පරීක්ෂා කිරීමට අවශ්‍ය නම්, පහත සඳහන් සියලු වැඩ, සහ දිගුව ඉවත් කරන්න:

FILE=abc.xyz; echo ${FILE%.*};
FILE=123.abc.xyz; echo ${FILE%.*};
FILE=abc; echo ${FILE%.*};

2
පහත වැටීම ඇයි? සං around ා වටා අවකාශයක් නොතිබිය යුතු වුවද එය තවමත් ප්‍රයෝජනවත් වේ =.
සිල්වර් වුල්ෆ් - මොනිකා නැවත

1
මෙය හොඳින් ක්‍රියාත්මක වේ. ඔබට ස්තුතියි! (දැන් එයට සමාන සලකුණු වටා අවකාශයක් නොමැත, ඒ නිසා එය පහත් කොට සලකනු ලැබුවේ නම්)
ඇලෙක්ස්. එස්.

4

බොහෝ දුරට @ mklement0 හි විශිෂ්, හා අහඹු, ප්‍රයෝජනවත් බැෂිම් වලින් පිරී ඇත - මෙන්ම මෙම / වෙනත් ප්‍රශ්න වලට පිළිතුරු / "එම අන්තර්ජාලය" ... මම ඒ සියල්ල මඳක් ඔතා, තරමක් තේරුම්ගත හැකි, මගේ (හෝ ඔබගේ) නැවත භාවිතා කළ හැකි කාර්යය.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 extensionless 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
}     

භාවිත උදාහරණ ...

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>

1
හොඳට කලා; යෝජනා කිහිපයක්: - ඔබ කිසිසේත් විශ්වාසය තබන බවක් නොපෙනේ $IFS(ඔබ එසේ නම්, localඑය සැකසීමේ බලපෑම දේශීයකරණය කිරීමට ඔබට භාවිතා කළ හැකිය ). - localවිචල්යයන් භාවිතා කිරීමට වඩා හොඳය . - ඔබගේ දෝෂ පණිවිඩය ප්‍රතිදානය විය යුතුය (භාවිතා stderrනොකර ), ඔබ ශුන්‍ය නොවන පිටවීමේ කේතයක් ලබා දිය යුතුය. - නැවත නම් කිරීම වඩා හොඳය (කලින් යෝජනා කර ඇත්තේ dir සංරචක සහිත මාර්ගයක්). - මුල් පිටපත කිසිවක් නොතිබුණද කොන්දේසි විරහිතව (කාල ​​පරිච්ඡේදයක්) එකතු කරයි. ඔබට හුදෙක් උපයෝගීතාව භාවිතා කළ හැකිය, නමුත් එය අවසන් කිරීම නොසලකා හරින බව සලකන්න . stdout1>&2fullnamebasenamename.basename/
mklement0

3

පීටෙෂ් පිළිතුරෙන් ගොඩනැගීම , ගොනු නාමය පමණක් අවශ්‍ය නම්, මාර්ගය සහ දිගුව යන දෙකම තනි පේළියකින් ඉවත් කළ හැකිය,

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

මා වෙනුවෙන් වැඩ කළේ නැත: "මූලික නම: අස්ථානගත වූ ක්‍රියාකාරිත්වය වැඩි විස්තර සඳහා 'basename --help' උත්සාහ කරන්න."
හෙල්මි

අමුතුයි, ඔබ Bash භාවිතා කරන බව ඔබට විශ්වාසද? මගේ නඩුවේදී, 3.2.25 (පැරණි සෙන්ටෝස්) සහ 4.3.30 (ඩේබියන් ජෙසී) යන අනුවාද දෙකම දෝෂ රහිතව ක්‍රියා කරයි.
cvr

සමහර විට ගොනු නාමයේ ඉඩක් තිබේද? භාවිතා කිරීමට උත්සාහ කරන්නfilename="$(basename "${fullname%.*}")"
ඒඩ්‍රියන්

දෙවන තර්කය basenameඅත්‍යවශ්‍ය නොවේ, නමුත් ඉවත් කිරීම සඳහා දිගුව නියම කරයි. ආදේශනය තවමත් ප්‍රයෝජනවත් විය හැකි නමුත් සමහර විට basenameඇත්ත වශයෙන්ම එසේ නොවේ, මන්ද ඔබට මෙම ආදේශක සියල්ලම ෂෙල් බිල්ඩින් සමඟ කළ හැකිය.
ත්‍රිත්ව

2

සරල පිළිතුරක්:

POSIX විචල්ය පිළිතුරු පුළුල් කිරීම සඳහා , ඔබට වඩාත් රසවත් රටා කළ හැකි බව සලකන්න. එබැවින් මෙහි විස්තර කර ඇති නඩුව සඳහා, ඔබට මෙය කළ හැකිය:

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

එය .tar හි අවසාන සිදුවීම කපා දමනු ඇත. <something> .

වඩාත් සාමාන්‍යයෙන්, ඔබට අවසාන සිදුවීම ඉවත් කිරීමට අවශ්‍ය නම්. <something> . <something-else> එවිට

${1.*.*}

හොඳින් වැඩ කළ යුතුයි.

ඉහත පිළිතුර සබැඳිය මිය ගොස් ඇති බව පෙනේ. ටීඑල්ඩීපී වෙතින් ඔබට කෙලින්ම බාෂ් හි කළ හැකි නූල් හැසිරවීමේ පොකුරක් පිළිබඳ විශිෂ්ට පැහැදිලි කිරීමක් මෙන්න .


තරගය නඩුව-සංවේදී නොවන බවට පත් කිරීමට ක්‍රමයක් තිබේද?
ටොනික්ස්

2

ඔබටත් හිස් දිගුවන්ට ඉඩ දීමට අවශ්‍ය නම්, මට ඉදිරිපත් කළ හැකි කෙටිම කාලය මෙයයි:

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

1 වන පේළිය පැහැදිලි කර ඇත: එය PATH.EXT හෝ ANYTHING සමඟ ගැලපෙන අතර එය EXT සමඟ ප්‍රතිස්ථාපනය කරයි. කිසිවක් ගැලපෙන්නේ නම්, අමතර කණ්ඩායම අල්ලා නොගනී.


2

මා වෙනුවෙන් වැඩ කළ එකම එක මෙයයි:

path='folder/other_folder/file.js'

base=${path##*/}
echo ${base%.*}

>> file

මෙය නූල් අන්තර් මැදිහත්වීමේදීද භාවිතා කළ හැකිය, නමුත් අවාසනාවකට ඔබ baseකලින් සැකසිය යුතුය.


1

ආවරණයක් සම්බන්ධයෙන් නම් ගැටෙන විට නම් අද්විතීය කිරීමට නම් මම බාෂ් ස්ක්‍රිප්ට් එකක් ලියන විට ගොනුවක නම සහ දිගුව සොයා ගැනීම සඳහා භාවිතා කළ ඇල්ගොරිතම මෙන්න.

#! /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 

පරීක්ෂණ ධාවනය.

$ 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: සම්පූර්ණ අක්ෂර පරිවර්තන වැඩසටහන සහ තවත් පරීක්ෂණ අවස්ථා මෙහි සොයාගත හැකිය: https://www.dropbox.com/s/4c6m0f2e28a1vxf/avoid-clashes-code.zip?dl=0


සියළුම විසඳුම් වලින් ගොනුව සමඟ දිගුවක් නොමැති විට හිස් නූලක් ලබා දෙන එකම ක්‍රමය මෙයයි:extension=$([[ "$theFileName" == *.* ]] && echo ".${theFileName##*.}" || echo '')
f0nzie

1

උදාහරණ ගොනුව භාවිතා කරමින් /Users/Jonathan/Scripts/bash/MyScript.sh, මෙම කේතය:

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

${ME}පැවැත්ම MyScriptහා ${MY_EXT}පැවැත්මේ ප්‍රති result ලය වනු ඇත .sh:


පිටපත:

#!/bin/bash
set -e

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

echo "${ME} - ${MY_EXT}"

සමහර පරීක්ෂණ:

$ ./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

2
මෙයට අඩු අගයක් ඇත්තේ මන්දැයි නිශ්චිතවම කිව නොහැක - එය ඇත්ත වශයෙන්ම පිළිගත් පිළිතුරට වඩා කාර්යක්ෂම වේ. (දෙවැන්න ලෙස, එය දිගුවක් නොමැතිව ආදාන ගොනු නාමයන් සමඟ ද කැඩී යයි ). පැහැදිලි මාර්ගයක් භාවිතා කිරීම basename, සමහර විට, අධික ලෙස මරා දැමීමකි.
mklement0

1

ඉහත පිළිතුරු වලින්, පයිතන් අනුකරණය කිරීමට කෙටිම ඔනලයිනර් ය

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

ඔබේ ගොනුවට දිගුවක් තිබේ යැයි උපකල්පනය කිරීම

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

මට මේ ගැන අඩු අගයක් තියෙනවා. පිළිතුර ඉවත් කිරීමට මම සලකා බලමි, මිනිසුන් කෙසේ හෝ එයට අකමැතියි.
commonpike

basename මඟින් දිගුව ඉවත් නොකරයි, මාර්ගය පමණි.
ඩේවිඩ් කලන්

SUFFIX විකල්පය ගැන මට අමතක වූ man පිටුව දෙස බැලීමෙන් මෙතරම් කාලයක් ගත වී ඇත.
ඩේවිඩ් කලන්

දැමිය යුතු දේ දැන ගැනීමට පෙර ඔබට ඉවත් කිරීමට අවශ්‍ය දිගුව කුමක්දැයි ඔබ දැන සිටිය යුතුය, EXTඑවිට මෙය කැස්බෑවන් වේ. (එසේම, ඔබේ පුද්ගලික විචල්‍ය නම් සඳහා වන සියලුම ලොකු අකුරු වලින් වැළකී සිටිය යුතුය; ඒවා පද්ධති විචල්‍යයන් සඳහා වෙන් කර ඇත.)
ත්‍රිත්ව
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.