37 Soru: Bash'deki dosya adını ve uzantısını çıkarın

tarafından oluşturulan soru Tue, Jul 10, 2018 12:00 AM

Dosya adını (uzantısız) ve uzantıyı ayrı ayrı almak istiyorum.

Şu ana kadar bulduğum en iyi çözüm:

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

Bu yanlıştır, çünkü dosya adı birden fazla . karakter içeriyorsa çalışmaz. Diyelim ki, a.b.js’um varsa, a ve b.js yerine a.b ve js’u dikkate alacaktır.

Python'da

ile kolayca yapılabilir.  
file, ext = os.path.splitext(path)

ancak mümkünse bunun için bir Python tercümanı ateşlememeyi tercih ederim.

Daha iyi bir fikrin var mı?

    
1853
  1. 2009-06-12 20: 34: 31Z
  2. Aşağıdaki harika yanıtları uygularken, burada gösterdiğim gibi değişkeninize yapıştırmayın Yanlış: Bir süredir yaptığım gibi extension="{$filename##*.}"! $'u kıvırcıkların dışına taşıyın: Sağ: extension="${filename##*.}"
    2013-08-07 18: 51: 56Z
  3. Bu açıkça önemsiz bir sorun ve benim için aşağıdaki cevapların tamamen doğru olup olmadığını söylemek zor. Bu, (ba) sh işlevinde yerleşik bir işlem değildir (cevaplar, desen eşleştirmeyi kullanarak işlevi yerine getirir). Python'un os.path.splitext'unu yukarıdaki gibi kullanmaya karar verdim ...
    2015-10-01 08: 01: 06Z
  4. uzantısı bir dosyanın yapısını temsil etmek zorunda olduğu için, sihir vardır Dosyasını, onun yapısını ilahi hale getiren ve standart uzantı 'yı önerecek komutu kontrol edin. Cevabım
    'a bakın.
    2016-10-14 08: 02: 53Z
  5. Soru ilk etapta sorunlu çünkü .. OS ve unix dosya sistemleri açısından genel olarak dosya uzantısı diye bir şey yoktur. "." Kullanarak parçaları ayırmak, yalnızca insanlar onu takip etmeyi kabul ettiği sürece işe yarayan bir insan sözleşmesidir . Örneğin, 'tar' programıyla, çıktı dosyalarını "tar" olarak adlandırmaya karar verilebilirdi. ".tar" soneki yerine önek - "somedir.tar" yerine "tar.somedir" verilmesi. Bundan dolayı "genel, her zaman işe yarayan" bir çözüm yoktur - bunun için özel gereksinimlerinize ve beklenen dosya adlarına uyan bir kod yazmanız gerekir.
    2018-10-10 00: 08: 42Z
30 Yanıtlar                              30                         

İlk önce dosya yolunu yolsuz olsun:

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

Alternatif olarak, 'yerine' yolun son '/' bölümüne odaklanabilirsiniz. Tahmin edilemeyen dosya uzantılarınız olsa bile hangisi işe yarayabilir:

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

Dokümanları kontrol etmek isteyebilirsiniz:

3166
2018-11-11 05: 41: 47Z
  1. 2009-06-08 14: 08: 51Z
  2. "$fullfile" ifadesine bazı alıntılar ekleyin, yoksa dosya adını bozma riskiyle karşılaşırsınız.
    2009-06-08 14: 34: 48Z
  3. Heck, dosya adını bile yazabilirsiniz = "${fullfile ## * /}" ve fazladan 493'ü aramaktan kaçının10
    2009-06-09 17: 52: 24Z
  4. Dosya bir uzantıya sahip değilse bu "çözüm" çalışmaz - bunun yerine, tüm dosya adı çıktıdır; her yerde hazır.
    2012-07-01 03: 42: 00Z
  5. Uzantı olmayan dosya adlarıyla ilgilenmek için düzeltme: basename. Eğer bir uzantı mevcutsa, ilk extension=$([[ "$filename" = *.* ]] && echo ".${filename##*.}" || echo ''), örneğin, . da dahil olmak üzere geri gönderileceğini unutmayın.
    2012-09-07 14: 41: 40Z
 .txt

Daha fazla ayrıntı için bkz. kabuk parametresi genişletme Bash kılavuzunda.

    
576
2015-04-20 16: 58: 03Z
  1. Siz (belki de istemeyerek) dosya adının "extension" kısmı .tar.gz'de olduğu gibi içinde 2 nokta varsa ne yapılacağına dair mükemmel bir soru ortaya çıkarıyor ... bu konuyu hiç düşünmedim ve olası tüm geçerli dosya uzantılarını bilmeden çözülemeyeceğinden şüpheliyim.
    2009-06-08 14: 50: 20Z
  2. Neden çözülebilir değil? Örneğimde, dosyanın iki noktalı bir uzantı değil iki uzantı içerdiği düşünülmelidir. Her iki uzantıyı ayrı ayrı işlersiniz.
    2009-06-08 15: 20: 49Z
  3. Sözcüksel olarak çözülemez, dosya türünü kontrol etmeniz gerekir.
    ~% FILE="example.tar.gz"
    ~% echo "${FILE%%.*}"
    example
    ~% echo "${FILE%.*}"
    example.tar
    ~% echo "${FILE#*.}"
    tar.gz
    ~% echo "${FILE##*.}"
    gz
    
    adında bir oyun yapıp yapmadığınızı ve bunu dinosaurs.in.tar seviyesine getirdiğinizi düşünün :)
    2009-06-13 09: 11: 04Z
  4. Tam yollardan geçiyorsanız, bu daha karmaşık hale gelir. Birimde bir '' vardı. yolun ortasındaki bir dizinde, ancak dosya adında yok. Örnek "a /b.c /d /e /dosyaadı", ".c /d /e /dosyaadı" nı alırdı
    2012-03-05 18: 49: 56Z
  5. açıkça dinosaurs.in.tar.gz'un uzantısı x.tar.gz ve dosya adı gz'dur. İkili uzantı diye bir şey yoktur. Ben eminim boost :: filesystem bu şekilde işler. (split path, change_extension ...) ve davranışları yanılmıyorsam python'a dayanıyor.
    2013-11-26 07: 29: 17Z

Genellikle uzantıyı zaten biliyorsunuzdur, bu nedenle kullanmak isteyebilirsiniz:

 x.tar

örneğin:

 
basename filename .extension

ve alırız

 
basename /path/to/dir/filename.txt .txt
    
346
2011-10-19 10: 56: 09Z
  1. filename
    
    'daki bu ikinci argüman oldukça göz açıcı, ty kind efendim /madam :)
    2013-01-23 09: 37: 43Z
  2. Ve bu tekniği kullanarak uzantı nasıl çıkartılır? ;) Bekle! Aslında bunu önceden bilmiyoruz.
    2014-02-13 11: 48: 21Z
  3. basename veya .zip ile biten bir sıkıştırılmış dizinin olduğunu söyleyin. .ZIP gibi bir şey yapmanın bir yolu var mı?
    2014-03-30 20: 56: 25Z
  4. Bu, OPs sorusunun sadece bir kısmını cevaplarken, google'a yazdığım soruyu cevaplıyor. :-) Çok kaygan!
    2017-11-30 16: 28: 28Z
  5. kolay ve POSIX uyumlu
    2018-10-12 15: 36: 32Z

POSIX değişkenlerinin büyüsünü kullanabilirsiniz:

 basename $file {.zip,.ZIP}

Eğer dosya adınız

bash-3.2$ FILENAME=somefile.tar.gz
bash-3.2$ echo ${FILENAME%%.*}
somefile
bash-3.2$ echo ${FILENAME%.*}
somefile.tar
biçimindeyse, ./somefile.tar.gz'un echo ${FILENAME%%.*} ile en uzun eşleşmeyi nazikçe kaldıracağı ve boş dizeye sahip olacağınıza dair bir uyarı var.

(Bunun üzerinde geçici bir değişkenle çalışabilirsiniz:

 .

)


Bu site daha fazla açıklıyor.

 
FULL_FILENAME=$FILENAME
FILENAME=${FULL_FILENAME##*/}
echo ${FILENAME%%.*}
    
133
2013-02-05 15: 40: 05Z
  1. Joachim'in cevabından çok daha basit ama her zaman POSIX değişkeninin değişimini aramak zorundayım. Ayrıca, bu,
    ${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
    
    ’un cut’a sahip olmadığı ve --complement’un sed’unun olmadığı Max OSX’de çalışır.
    2014-07-18 16: 40: 25Z

Dosyanın uzantısı yoksa veya dosya adı yoksa, bu işe yaramaz gibi görünüyor. İşte kullanıyorum ne; yalnızca yerleşikleri kullanır ve daha fazlasını (ancak hepsini değil) patolojik dosya adlarını kullanır.

 -r

Ve işte bazı test senaryoları:

 
#!/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
    
68
2009-09-10 06: 13: 08Z
  1. $ 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 = "file"
        ext  = ""
    /home/me/file.tar:
        dir  = "/home/me/"
        base = "file"
        ext  = "tar"
    /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  = "tar"
    /home/me/..:
        dir  = "/home/me/"
        base = ".."
        ext  = ""
    .:
        dir  = ""
        base = "."
        ext  = ""
    
    yerine dir="${fullpath:0:${#fullpath} - ${#filename}}"'u sık sık gördüm. Yazması daha kolay. Gerçek bir hız farkı ya da farkları olup olmadığından emin değilim.
    2012-05-30 21: 37: 31Z
  2. Bu, neredeyse her zaman yanlış olan #! /bin /bash öğesini kullanır. Mümkünse #! /Bin /sh, veya eğer değilse #! /Usr /bin /env bash tercih edin.
    2013-05-25 20: 32: 03Z
  3. @ İyi Kişi: Neredeyse her zaman nasıl yanlış olduğunu bilmiyorum: dir="${fullpath%$filename}" - > which bash; belki de senin dağıtımın?
    2013-07-10 22: 30: 54Z
  4. @ vol7ron - birçok dağıtımda /usr /local /bin /bash dizininde. OSX'te çoğu kişi /opt /local /bin /bash içine güncellenmiş bir bash kurar. Gibi /bin /bash yanlış ve bir bulmak için env kullanmalısınız. Daha da iyisi /bin /sh ve POSIX yapılarını kullanmaktır. Solaris dışında bu bir POSIX kabuğu.
    2013-07-12 21: 28: 04Z
  5. @ GoodPerson, ancak bash konusunda daha rahatsanız, neden sh kullanmalısınız? Söylemek istemedi, sh kullanabiliyorken neden Perl kullanıyorsunuz?
    2013-07-12 22: 08: 32Z

/bin/bash adresini kullanabilirsiniz.

Örnek:

 basename

Kaldırılacak uzantıyla bir temel ad sağlamanız gerekir, ancak

$ basename foo-bar.tar.gz .tar.gz
foo-bar
ile her zaman tar yürütüyorsanız, uzantının -z olacağını bilirsiniz.

Bu istediğini yapmalı:

 .tar.gz     
42
2013-02-05 08: 56: 05Z
  1. tar -zxvf $1
    cd $(basename $1 .tar.gz)
    
    'un .gz dosyaları için çalıştığını düşünüyorum. Ancak söz konusu konuda cd $(basename $1 .tar.gz)'dan söz etti
    2013-02-05 09: 00: 00Z
  2. Tomi Po, 2 yıl önce aynı şeyleri gönderdi.
    2017-09-16 02: 38: 07Z
  3. Merhaba, Blauhirn, bu eski bir soru. Sanırım tarihlere bir şey oldu. Soruyu sorulduktan kısa bir süre sonra soruyu yanıtlamayı özel olarak hatırlıyorum.orada sadece birkaç başka cevap var. Sorunun bir başkasıyla birleştirilmesi olabilir mi, SO bunu yapıyor mu?
    2017-09-17 04: 43: 24Z
  4. Evet Doğru hatırlıyorum. Bu soruyu orjinalde cevaplandırıyorum 2017-09-17 04: 49: 34Z
 Archive files have several extensions: tar.gz, tat.xz, tar.bz2

iyi çalışıyor, bu nedenle yalnızca şunları kullanabilirsiniz:

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

Bu arada, komutlar aşağıdaki gibi çalışır.

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
için verilen komut, NAME karakterinin ardından "." karakter olmayan, ardından "." karakterinin yerine, hiçbir şey olmadan (yani, son "."'dan satır sonuna kadar her şeyi kaldırır) değiştirir. Bu temelde regex kandırıcılığını kullanan açgözlü olmayan bir oyuncu değişikliğidir.

EXTENSION komutu, satır başında "." karakterinin ardından gelen herhangi bir sayıdaki karakterin yerine hiçbir şey yapmaz (yani, satırın başlangıcından son noktaya kadar her şeyi kaldırır). Bu, varsayılan işlem olan açgözlü bir değişikliktir.

    
29
2017-09-05 01: 07: 22Z
  1. Bu, dosya adı ve uzantı için aynı şekilde yazdırılacağı için uzantısı olmayan dosyalar için. Bu nedenle, ad için sed 's,\.[^\.]*$,,', uzantı için sed 's,.*\.,., ;t ;g' kullanıyorum (tipik test komutuyla birlikte atipik get ve substitute komutlarını kullanır).
    2018-10-07 05: 11: 06Z

Mellen bir blog yazısına yaptığı bir yorumda şöyle yazar:

Bash'i kullanarak, dosya adını uzantı olmadan almak için ${file%.*} ve uzantıyı yalnızca almak için ${file##*.} vardır. Bu,

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

Çıktılar:

 
filename: thisfile
extension: txt
    
27
2015-04-20 16: 58: 54Z
  1. Bu sözdizimi tam olarak nasıl çalışır?
    2014-10-15 11: 26: 13Z
  2. 2014-12-09 15: 30: 14Z

Son iki uzantıyı (cut bölüm) kaldırmak için ".tar.gz" komutunu kullanabilirsiniz:

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

Bir yorumda Clayton Hughes tarafından belirtildiği gibi, bu sorudaki gerçek örnek için işe yaramayacaktır. Alternatif olarak, sed'u genişletilmiş düzenli ifadelerle kullanmayı öneriyorum, bunun gibi:

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

Son iki (alfa sayısal) uzantıyı koşulsuz olarak kaldırarak çalışır.

[Anders Lindahl yorumundan sonra tekrar güncellendi]

    
25
2013-12-04 08: 08: 34Z
  1. Bu, yalnızca dosya /yolun başka noktalar içermemesi durumunda çalışır: echo "mpc-1.0.1.tar.gz" | -d 'kes.' --complement -f2- "mpc-1" i üretir (tarafından sınırlandırıldıktan sonra sadece ilk 2 alan.)
    2013-12-04 00: 39: 29Z
  2. @ ClaytonHughes Haklısınız ve daha iyi test etmeliydim. Başka bir çözüm eklendi.
    2013-12-0407: 52: 18Z
  3. Üst ifadeler, eşleşen uzantının dosya adının sonunda olduğunu kontrol etmek için $ kullanmalıdır. Aksi takdirde, i.like.tar.gz.files.tar.bz2 gibi bir dosya adı beklenmeyen bir sonuç verebilir.
    2013-12-04 07: 56: 35Z
  4. @ AndersLindahl Bu, uzantıların sırası sed zincir sırasının tersi ise, yine de devam edecek. Sonunda $ olsa bile, mpc-1.0.1.tar.bz2.tar.gz gibi bir dosya adı hem .tar.gz'u, sonra .tar.bz2'u kaldıracaktır.
    2013-12-04 08: 03: 05Z

Bu basit görev için awk veya sed veya hatta perl ile uğraşmanıza gerek yok. Yalnızca parametre genişletmelerini kullanan saf Bash os.path.splitext() uyumlu bir çözüm var.

Referans Uygulaması

os.path.splitext(path) 'un dokümantasyonu p>

  

Yol adı yolunu (root, ext) çiftine bölün, root + ext == path ve ext boş veya bir nokta ile başlar ve en fazla bir periyod içerir. Temel addaki önde gelen dönemler dikkate alınmaz; splitext('.cshrc'), ('.cshrc', '') değerini döndürür.

Python kodu:

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

Bash Uygulaması

Önde gelen dönemleri onaylamak

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

Önümüzdeki dönemleri dikkate almamak

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

Testler

Her girişte Python referans uygulamasıyla eşleşmesi gereken Önümüzdeki dönemleri Yoksayma uygulamasının test durumları aşağıdadır.

 
|---------------|-----------|-------|
|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' |
|---------------|-----------|-------|

Test Sonuçları

Tüm testler geçti.

    
24
2016-12-19 23: 35: 04Z
  1. hayır, text.tar.gz için temel dosya adı text olmalı ve uzantı .tar.gz olmalıdır
    2018-11-16 17: 22: 15Z
  2. @ frederick99 Dediğim gibi, buradaki çözüm Python'da os.path.splitext uygulamasıyla eşleşiyor. Uygulamanın muhtemelen tartışmalı girdiler için akıllıca olup olmadığı bir başka konudur.
    2018-12-25 19: 11: 37Z
  3. Desen ("$root") içindeki alıntılar nasıl çalışır? İhmal edilirse ne olabilir? (Konuyla ilgili herhangi bir belge bulamadım.) Ayrıca, bu dosyalarda * veya ? dosya adlarını nasıl kullanır?
    2019-06-12 08: 14: 18Z
  4. Tamam, testler bana alıntıların kalıbı gerçek bir hale getirdiğini gösteriyor, yani * ve ? özel değildir. Yani sorumun iki kısmı birbirlerine cevap veriyor. Bunun belgelenmemiş olması doğru mudur? Yoksa bunun genel olarak küresel büyümenin etkisiz hale getirildiğinden alıntıların anlaşılması mı gerekiyor?
    2019-06-12 08: 25: 16Z

Yazılım paketleri için sürüm numaraları çıkarma gibi bazı gelişmiş kullanım durumları da dahil olmak üzere bazı alternatif öneriler (çoğunlukla awk'da).

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

Tüm kullanım durumları, ara sonuçlara bağlı olmadan, orijinal tam yolu giriş olarak kullanıyor.

    
20
2015-06-16 09: 02: 52Z

En küçük ve en basit çözüm (tek satırda) şudur:

 
$ file=/blaabla/bla/blah/foo.txt
echo $(basename ${file%.*}) # foo
    
16
2018-11-30 09: 34: 59Z
  1. Bu bir yararsızdır echo’un kullanımı . Genel olarak, echo $(command), çıkışta beyaz boşluk belirtimi ve joker karakter genişletmesi yapmak için özel olarak kabuk istemediğiniz sürece, sadece command daha iyi yazılır.sonucu görüntülemeden önce m command. Test: echo $(echo '*')'un çıktısı nedir (ve gerçekten istediğiniz buysa, gerçekten gerçekten sadece echo *'u istiyorsunuz).
    2017-11-10 10: 34: 17Z
  2. @ triplee echo komutunu hiç kullanmadım. Ben sadece ikinci satırın sonucu olarak 3. satırda ortaya çıkan foo sonucunu göstermek için kullandım.
    2018-04-17 10: 07: 42Z
  3. Ama sadece basename "${file%.*}" da aynısını yapardı; Çıktısını yakalamak için bir komut ikamesi kullanıyorsunuz, sadece hemen aynı çıktı echo'a kadar. (Alıntı vermeden, sonuç nominal olarak farklıdır; ancak bu çok ilgili değil, burada çok daha az bir özellik var.)
    2018-04-17 10: 35: 30Z
  4. Ayrıca basename "$file" .txt, parametre değiştirmenin karmaşıklığından kaçınır.
    2018-04-17 11: 21: 02Z
  5. İlgisiz şeyler hakkında konuşmadan ve zamanımızı boşa harcamadan önce önceki cevabımı dikkatlice okuyun. Teşekkür
    2018-04-18 17: 17: 03Z

kabul edilen cevap , tipik durumlarda iyi çalışır, ancak son durumlarda başarısız olur, yani:

  • Uzantı içermeyen dosya adları için (bu yanıtın geri kalan kısmında sonek olarak adlandırılır), extension=${filename##*.}, boş bir dize yerine giriş dosya adını döndürür.
  •  extension=${filename##*.}, sözleşmeye aykırı, ilk .’u içermez.
    • Kör 49110'un kör olarak hazırlanması, son ekler olmadan dosya adları için işe yaramaz.
  •  Giriş dosyası adı . ile başlıyorsa ve başka filename="${filename%.*}" karakter içermiyorsa (ör., .) ., boş dize olacaktır (örneğin, .bash_profile).

---------

Bu nedenle, tüm son durumları kapsayan sağlam bir çözümün karmaşıklığı bir işlev ister - tanımını aşağıya bakın; bir yolun tüm bileşenlerini döndürebilir .

Örnek arama:

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

Girdi yolundan sonraki argümanların serbestçe seçildiğine, konumsal değişken adlarının olduğuna dikkat edin.
Olanlardan önce gelmeyen ilgi çekici olmayan değişkenleri atlamak için _ ($_ atma değişkenini kullanmak için) veya ''; örneğin, yalnızca dosya adı kökünü ve uzantısını çıkarmak için splitPath '/etc/bash.bashrc' _ _ fnameroot extension kullanın.


 
# 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

İşlevi uygulayan test kodu:

 
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

Beklenen çıktı - son durumlara dikkat edin:

  • son eki olmayan bir dosya adı
  • . ile başlayan bir dosya adı ( değil son ekin başlangıcı olarak kabul edildi)
  • / ile biten bir giriş yolu (izleyen / yoksayılır)
  • yalnızca dosya adı olan bir giriş yolu (., ana yol olarak döndürülür)
  • .'dan fazla öneklenmiş jetona sahip bir dosya adı (yalnızca son ek olarak kabul edilir):
 
----- /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
    
14
2019-02-14 22: 44: 43Z

Bence sadece dosya adına ihtiyacınız varsa, şunu deneyebilirsiniz:

 
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"

Hepsi bu = D.

    
12
2015-04-20 17: 00: 14Z
  1. Yeni aranan BASEDIRECTORY :) Teşekkürler!
    2012-12-09 20: 42: 56Z

Tüm alanları ve ardından gelenleri alan numarasına - ekleyenleri göstermeye zorlayabilirsiniz.

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

Öyleyse, DOSYA eth0.pcap.gz ise, GENİŞLETME pcap.gz olur

Aynı mantığı kullanarak, dosya adını '-' kullanarak aşağıdaki gibi kesilmiş olarak da alabilirsiniz:

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

Bu, uzantısı olmayan dosya adları için bile çalışır.

    
10
2015-07-30 16: 23: 11Z

Sihirli dosya tanıma

Bu Yığın Taşması sorusundaki iyi cevapların yanı sıra eklemek istiyorum:

Linux ve diğer unixen'lerde, file adında bir sihir komutu var ve bu dosya ilk birkaç baytı analiz ederek dosya tipi tespiti yapıyor. Bu, başlangıçta baskı sunucuları için kullanılan çok eski bir araçtır (eğer oluşturulmadıysa ... bundan emin değilim).

 
file myfile.txt
myfile.txt: UTF-8 Unicode text

file -b --mime-type myfile.txt
text/plain

Standart uzantıları /etc/mime.types'da bulunabilir ( Debian GNU /Linux masaüstünde bulunabilir. Bkz. man file) ve man mime.types. Belki de file yardımcı programını ve mime-support paketlerini yüklemelisiniz):

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

belirlemek için bir işlevini etiketleyebilirsiniz. sağ uzatma Küçük (mükemmel değil) bir örnek var:

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

Bu işlev daha sonra kullanılabilecek bir Bash değişkeni belirleyebilir:

(Bu @Petesh'in doğru cevabından ilham almıştır):

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

echo "$fullfile -> $filename . $extension"
    
7
2015-04-20 17: 04: 11Z

Tamam, bu yüzden doğru anlarsam, buradaki sorun birden fazla uzantıya sahip bir dosyanın adını ve tam uzantısını (örneğin, stuff.tar.gz, örneğin) almaktır.

Bu benim için çalışıyor:

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

Bu size dosya adı olarak stuff ve uzantı olarak .tar.gz verecektir. Bu, 0 da dahil olmak üzere herhangi bir sayıda uzantı için çalışır. Umarım bu, aynı sorunu yaşayan herkes için yardımcı olur =)

    
7
2016-12-02 10: 26: 40Z
  1. Doğru sonuç (OP'nin istediği şey olan os.path.splitext'a göre) ('stuff.tar', '.gz')'dur.
    2016-12-02 09: 15: 50Z

Aşağıdaki betiği kullanıyorum

 
$ echo "foo.tar.gz"|rev|cut -d"." -f3-|rev
foo
    
6
2014-03-22 12: 56: 10Z
  1. Bu hiç etkili değil. Çok fazla kez gereksiz olan çatallar için bu işlem gereksizdir, çünkü bu işlem herhangi bir harici komuta gerek kalmadan saf Bash'de gerçekleştirilebilir.
    2018-03-07 15: 13: 20Z
 
$ F = "text file.test.txt"  
$ echo ${F/*./}  
txt  

Bu, bir dosya adında birden fazla nokta ve boşluk sağlar, ancak uzantı yoksa, dosya adını kendisi döndürür. Olsa kontrol etmek kolay; sadece dosya adını ve uzantıyı aynı olması için test edin.

Doğal olarak, bu yöntem .tar.gz dosyaları için çalışmaz. Ancak bu iki aşamalı bir süreçte ele alınabilir. Uzantı gz ise, bir katran uzantısı olup olmadığını görmek için tekrar kontrol edin.

    
5
2011-04-10 13: 58: 28Z
  1. Olumlu oy verildi, ancak denemeden sonra bu çalışmıyor.
    2017-09-18 19: 32: 02Z

Dosya adını ve uzantısını balık 'da nasıl ayıklayabilirsiniz?

 
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

Uyarılar: Son noktayı böler; içinde nokta bulunan dosya adları için iyi çalışır, ancak içinde nokta bulunan uzantılar için iyi değildir. Aşağıdaki örneğe bakın.

Kullanım:

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

Bunu yapmanın daha iyi yolları olabilir. Cevabımı geliştirmek için düzenlemekten çekinmeyin.


Sınırlı bir uzantı kümesi varsauğraşacaksınız ve hepsini biliyorsunuz, şunu deneyin:

 
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

İlk örnek olarak bu uyarılmaz ihbarda bulunmaz, ancak kaçınılması gerektiğine bağlı olarak daha sıkıcı olabilmesi için her vakayı ele almanız gerekir.

    
4
2014-03-30 21: 41: 03Z

İşte AWK kodudur. Daha basit yapılabilir. Ancak AWK'da iyi değilim.

 
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
    
4
2015-04-20 17: 00: 58Z
  1. Son örnekte ilk awk ifadesine ihtiyacınız yok, değil mi?
    2013-04-05 21: 13: 38Z
  2. Başka bir split() yaparak Awk'den Awk'e borulama yapılmasını önleyebilirsiniz. awk -F / '{ n=split($2, a, "."); print a[n] }' uses /`üst düzey sınırlayıcı olarak ancak ikinci alanları .'a böler ve son öğeyi yeni diziden yazdırır.
    2017-11-10 10: 42: 01Z

Yalnızca dosya adı gerekliyse, Petesh yanıtından oluşturma, Hem yol hem de uzantı tek bir satırda sıyrılabilir,

 
filename=$(basename ${fullname%.*})
    
3
2017-05-23 12: 34: 45Z
  1. İşe yaramadı: "basename: missing operand Daha fazla bilgi için 'basename --help' komutunu deneyin."
    2016-01-20 17: 29: 32Z
  2. Garip, Bash kullandığınızdan emin misiniz? Benim durumumda, hem 3.2.25 (eski CentOS) hem de 4.3.30 (Debian Jessie) sürümleriyle kusursuz çalışıyor.
    2016-02-01 23: 14: 41Z
  3. Belki dosya adında bir boşluk var? filename="$(basename "${fullname%.*}")" kullanmayı deneyin
    2017-03-14 20: 08: 11Z
  4. basename için ikinci argüman isteğe bağlıdır, ancak çıkartılacak uzantıyı belirtir. İkame hala faydalı olabilir, ancak belki de basename aslında değil, çünkü bu ikame işlemlerinin hepsini kabuk yerleşikleri ile gerçekleştirebilirsiniz.
    2017-11-10 10: 38: 23Z

Basitçe ${parameter%word} kullanın

Senin durumunda:

 
${FILE%.*}

Test etmek istiyorsanız, izleyen tüm işler ve uzantıyı kaldırın:

 
FILE=abc.xyz; echo ${FILE%.*};
FILE=123.abc.xyz; echo ${FILE%.*};
FILE=abc; echo ${FILE%.*};
    
3
2018-05-14 15: 48: 43Z
  1. Neden önemsiz? = işaretlerinin çevresinde boşluk olmamasına rağmen yine de kullanışlıdır.
    2018-05-14 15: 24: 26Z
  2. Bu iyi çalışıyor. Teşekkür ederim! (şimdi eşit işaretlerin etrafındaki boşluklara sahip değil, bu yüzden düşürüldü ise)
    2018-12-19 03: 11: 26Z

Basit bir cevap:

POSIX değişkenleri 'ni genişletmek için Cevapla , daha ilginç desenler yapabileceğini unutma. Bu yüzden burada ayrıntılı olarak açıklanan durum için, bunu basitçe yapabilirsiniz:

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

Bu sonuncuyu kesecek.tar'ın ortaya çıkışı. < bir şey > .

Daha genel olarak, < bir şey> gt; . < başka bir şey> gt; o zaman

'nin son oluşumunu kaldırmak istiyorsanız  
${1.*.*}

iyi çalışmalı.

Yukarıdaki cevabın bağlantısı ölü gibi görünüyor. Doğrudan Bash ile yapabileceğiniz bir dizi dize işleminin harika bir açıklaması. , TLDP'den .

    
2
2015-04-20 17: 07: 49Z
  1. Eşleşmeyi büyük /küçük harfe duyarlı yapmanın bir yolu var mı?
    2015-01-02 09: 42: 01Z

boş uzantılara da izin vermek istiyorsanız, bulabildiğim en kısa şey bu:

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

1. satır açıklanmıştır: PATH.EXT veya ANYTHING ile eşleşir ve EXT ile değiştirilir. Bir şey eşleşirse, ext grubu yakalanmaz.

    
2
2018-01-17 16: 47: 03Z

Büyük ölçüde @ mklement0'ın mükemmelinden yola çıkıldı ve rastgele, kullanışlı temelleri ile - ve bu /diğer sorulara /- “internetten lanetli” diğer cevaplara dayandı ... hepsi biraz, biraz daha anlaşılır, yeniden kullanılabilir işlevi benim (veya senin) .bash_profile için neye dikkat edersem (benim düşündüğüm) dirname/basename / 'nin daha sağlam bir versiyonunun ne olması gerektiği sizde var mı ..

 
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
}     

Kullanım örnekleri ...

 
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>
    
2
2019-05-23 11: 06: 20Z
  1. Güzel bitti; Birkaç öneri: - $IFS'a hiç güvenmiyor görünüyorsunuz (ve eğer öyleyse, bunu ayarlamanın etkisini lokalize etmek için local'u kullanabilirsiniz). - local değişkenini kullanmak daha iyi. - Hata mesajınız stderr'a değil stdout'a verilmelidir (1>&2 kullanın) ve sıfır olmayan bir çıkış kodu döndürmelisiniz. - fullname ila basename'u yeniden adlandırmak daha iyidir (ilki dir bileşenleriyle bir yol önerir). - name orijinali olmasa bile koşulsuz olarak . (dönem) ekler. basename yardımcı programını kullanabilirsiniz, ancak sonlandırma /'u dikkate almadığını unutmayın.
    2013-11-26 14: 18: 42Z

/Users/Jonathan/Scripts/bash/MyScript.sh örnek dosyasını kullanarak bu kod:

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

, ${ME}’un MyScript ve ${MY_EXT}’un .sh olmasıyla sonuçlanır:


Senaryo:

 
#!/bin/bash
set -e

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

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

Bazı testler:

 
$ ./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
    
1
2014-12-09 16: 37: 11Z
  1. Bunun neden bu kadar aşağısı olduğuna emin değil - aslında kabul edilen cevaptan daha verimli. (İkincisi olarak, bir uzantı olmadan giriş dosya adlarını da keser). basename'a açık bir yol kullanmak, muhtemelen fazla zararlıdır.
    2014-12-09 16: 35: 52Z

Yukarıdaki yanıtlardan, Python’ları taklit eden en kısa oneliner

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

dosyanızın gerçekten bir uzantısı olduğunu varsayarsak,  

EXT="${PATH##*.}"; FILE=$(basename "$PATH" .$EXT)
    
1
2015-04-20 17: 04: 50Z
  1. Bu konuda oylarım var. Cevabı kaldırmayı düşünüyorum, insanlar bir şekilde beğenmezler.
    2014-12-11 11: 26: 11Z
  2. basenaben uzantıyı kaldırmaz, sadece yol.
    2016-02-09 17: 19: 03Z
  3. 2016-02-09 22: 04: 48Z
  4. SUFFIX seçeneğini unuttuğum man sayfasına baktığımdan beri çok uzun zaman geçti.
    2016-02-10 00: 13: 38Z
  5. txt veya .txt ile çalışmıyor.
    2016-12-14 23: 28: 14Z

IMHO'ya en iyi çözüm zaten verildi (kabuk parametresi genişletmesi kullanılarak) ve şu anda en iyi dereceye sahip olanlardır.

Bununla birlikte, yalnızca dumbs komutlarını kullanan, verimli olmayan ve hiç kimsenin ciddi şekilde kullanmaması gerekenleri ekledim:  

FILENAME=$(echo $FILE | cut -d . -f 1-$(printf $FILE | tr . '\n' | wc -l))
EXTENSION=$(echo $FILE | tr . '\n' | tail -1)

sadece eğlence için eklendi :-) :-)

    
1
2018-12-11 02: 16: 21Z

Dir'i daha kullanışlı hale getirmek için (giriş yolu olmayan bir yerel dosyanın giriş olarak belirtilmesi durumunda) şunları yaptım:

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

Bu, giriş dosyasının adına bir sonek eklemek gibi yararlı bir şey yapmanızı sağlar:

 
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"
    
0
2013-08-09 00: 05: 19Z
kaynak yerleştirildi İşte