Sed kullanarak sadece dosya adı nasıl alınır


18

Sed kullanarak sadece dosya adını nasıl alabilirim? Bende

out_file=$(echo $in_file|sed "s/\(.*\.\).*/\1mp4/g")

Ama ben de yolu /root/video.mp4alıyorum ve sadece istiyorum video.mp4.

Yanıtlar:


28

basenameGNU coreutils'den bu işi yapmanıza yardımcı olabilir:

$ basename /root/video.mp4
video.mp4

Dosyanın uzantısını zaten biliyorsanız, kaldırmak basenameiçin sözdizimini kullanarak başlatabilirsiniz basename NAME [SUFFIX]:

$ basename /root/video.mp4 .mp4
video

Ya da başka bir seçenek, son noktadan sonra her şeyi kullanarak sedşunları kesmek olabilir :

$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old

3
Sahip olduğunuz gibi kullanmak sed 's/\.[^.]*$//', (gizli) .filenameve .ve ..dizinler için başarısız olacaktır
Peter.O

9

En kolay çözüm, son görünüme kadar her şeyi kaldırmaktır /:

echo /root/video.mp4 | sed 's/.*\///'


5

Aşağıdaki yollardan birini kullanın:

out_file="${in_file##*/}"

out_file="$(basename $in_file)"

out_file="$(echo $in_file | sed 's=.*/==')"

out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"

ps. \(.*\.\)İfadenizde başlangıçtan noktaya ( /root/video.) kadar dizeyle eşleştiğinden aynı dizeyi alırsınız ve ardından .mp4orijinal dizenizdeki ile aynı olanı manuel olarak eklersiniz . Bunun s=.*\([^/]*\)=\1=yerine kullanmalısınız .

Güncelleme: (Birincisi düzeltildi)

Uzantısız tek dosya adını almak için şunları yapabilirsiniz:

out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"

out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"

out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'

Ancak bu yöntemlerden herhangi biriyle formatla dosya adı alıyorum ve sadece dosya adını almam ve manuel olarak yeni bir format koymam gerekiyor.
Shixons

Ah, bu mantıklı. Cevabımı güncelledim.
acele

@rush: Örneğin, adlı bir dosya için kenar durumlar olacaktır my.file.tar.gz.
bağışlar başarıyla

@donothings Başarıyla sonuncusunda eksik bir nokta sembolü vardı sedve awk. Sabit. Teşekkür ederim.
acele

4

Normal ifade kullanmanın temellerinden biri, joker kartı belirtirken desenlerin doğası gereği açgözlü olmasıdır. @UloBasEI tarafından önerilen cevap kesinlikle çalışan bir cevap olsa da, basename komutunun da kullanılmasını gerektirir. @Shixons'un orijinal sorusu sadece sed kullanarak bir çözüm ister.

Devam etmeden önce, hangi sed sürümünün hedef olduğunu bilmek her zaman yararlıdır. BSD varsayıyorum (OSX ile birlikte gönderildiği gibi).

Her şeyden önce, orijinal soruda önerilen desen işe yaramaz çünkü giriş dizesinin başlangıcından son noktaya kadar olan her şeyi yakalar. Çapa olmadan, bu arama her şeyi soldan sağa yutacaktır. Bu nedenle "/ 1" uyumlu desen, son noktaya kadar ve son noktaya kadar olan her şeydir. Birden çok noktalı bir dosya adı bile tamamen yutulacaktır. İstenen sonuç hiç değil.

İlk adım, kalıpları tanımlamak için bir strateji oluşturmaktır. Burada, dosya adının solundaki her şeyden kurtulmak istiyorsunuz (daha sonra uzantıyla ilgileneceğiz):

out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"

Arama dizenin başından itibaren eşleşir. "/.*" sıfır veya daha fazla kez eşleşir ve daha sonra her şeyi siler. Eşleşen desenleri "\ 1" ile yazdırıyoruz. Global olarak arama yapmıyoruz; ^ çapasını belirterek dizenin başından itibaren arıyoruz.

Parantezlerden kaçmak zorunda kalmamak için "-E" seçeneğini etkinleştirerek daha iyi netlik elde ederiz:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"

Şimdi sol tarafta bir parçamız var. Parçayı sağa ekleyelim. Sol parçayı desen olarak tutmamız gerektiğini unutmayın, çünkü sıfır veya daha fazla kez görünmesini bu şekilde belirleyebiliriz. Şimdi tek yaptığımız, sağdaki parça için bir model eklemek:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"

Yalnızca ikinci eşleşmeyi yazdırırız, böylece dosya adı dışında her şeyi atarız. Ancak yine de dosya adı uzantısını kaldırmamız gerekiyor.

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"

Sondaki "$" isteğe bağlıdır.

Son olarak, şu şekilde revize ettiğiniz yeni uzantıyı eklemek için:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"

Ek bir optimizasyon, göreli yolları işlemek için ilk eğik çizgiyi isteğe bağlı yapmaktır:

out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"

Basename yerine bir sed kalıbı ararken tembel olarak bu soruya rastladım . Bu komutu yüklü olmayan soyulmuş bir sistem üzerinde çalışıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.