Dosya adlarını listelemek için ancak yolu listelemek için find komutu nasıl kullanılır?
Çevrimiçi olarak bazı cevapları kontrol ettim, ancak -name
komutta bir parametre olduğunda çalışmıyorlar (belki yanlış bir şey yapıyorum, emin değilim). Yapmak istediğim şey sadece dosya adlarını listelemek (dizin / yol değil) ve daha karmaşık hale getirmek için, farklı uzantılarla aynı dosya adına sahibim, bu yüzden sonucu -name
ve kullanarak filtrelemem gerekiyor -o
, sorun şu önerilerim ya ya -printf
da kullandığını gördü basename
ve var olduğunda bunlar iyi çalışmıyor -name *.txt -o name *.pdf
. Bu sorunu çözmenin başka bir yolu var mı?
Dosyalarımın örneği:
/dir1/dir2/dir3/dir4/
/file1.txt
/file1.pdf
/file1.ods ...etc.
Her giriş için yalnızca bir veya daha fazla dosya türünü listelemekle ilgileniyorum (kullanarak -name
sonuçlarımı filtrelemek için kullanarak .
Bunu yalnızca 1 find
komut kullanarak gerçekleştirmek mümkün mü yoksa bunu 2 adımda yapmak zorundayım (sonucu geçici bir dosyaya kaydetmek, ardından dizini geçici dosyadan filtrelemek / ayırmak)? Başarmaya çalıştığım sonuç, her satırda dosya adı olan bir metin dosyası:
file1.txt
file1.pdf
file1.ods
file2.txt
file2.pdf
etc.
Kullandığım komut
find /dir1/dir2/dir3/dir4/ -type f -name '*.txt' -o -name '*.pdf' -o -name '*.ods' -printf "%f\n"
GNU bulmayı kullanıyorum.
Güncelleme
\(...\)
Αғsнιη tarafından hatırlatıldığı gibi , koymak zorunda olduğum ortaya çıktı.
Yanıtlar
Mantıksal OR modunda birden çok ifade kullanırken -o
hepsini içine almanız gerekir \( ... \)
, aksi takdirde son ifade sonucuna her zaman saygı gösterilir; ve -printf '%f\n'
dosyaların adını yalnızca önde gelen dizinleri kaldırarak yazdırmak için kullanılır.
find . -type f \( -name '*.pdf' -o -name '*.txt' \) -printf '%f\n'
bkz man findaltında OPERATÖRLERİ hakkında bölümüne ( expr )
:
OPERATÖRLER
...(ifade)
Öncelik zorla . Parantezler kabuğa özel olduğundan, normalde bunları tırnak içine almanız gerekir.
bu yüzden onlardan kaçmak için \( ... \)
veya '(' ... ')'
(parantezden sonraki ve önceki boşluklar önemlidir) kullanabilirsiniz.
Daha önce de belirtildiği gibi, -name
testlerinizi parantez içinde gruplamanız gerekir . Bu parantezlerin \( ... \)
, örneğin '(' ... ')'
onları kabuktan korumak için (aksi takdirde bir alt kabuk olarak adlandırılacakları) olarak çıkarılması veya alıntılanması gerekir .
Standart kullanmak find
ve ayrıca dosya adı son eklerinin işlenmesini biraz daha kolaylaştırmak:
set -- txt pdf ods
for suffix do
set -- "$@" -o -name "*.$suffix"
shift
done
shift
find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename {} \;
Bu, ilk olarak konumsal parametreleri görmek istediğimiz dosya adı sonekleri listesine ayarlar (bu bir komut dosyası ise komut satırından da alınabilir) ve -name
testlerin OR listesini oluşturur . Bu daha sonra find
komut satırında kullanılır.
find
Komut kendisi aranmamanızı basename
her bulunan adı için yarar.
Alternatif olarak, her bir yol adının dosya adı bileşeni hariç tümünü kaldırmak için bir parametre ikamesi kullanabiliriz, ancak bunu yapmak için yol adlarını bir satır içi sh -c
betiğe aktarmalıyız:
# [...] as before [...]
find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec sh -c '
for pathname do
printf "%s\n" "${pathname##*/}"
done' sh {} +
Bunun kullanılan varyasyondan daha hızlı çalışmasını beklerdim basename
, en azından işlenecek çok sayıda dosya adı varsa, ancak basename
coreutils'teki GNU ile bunu kullanabilir -a
veya --multiple
beğenebilirsiniz:
find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename -a {} +
Bu basename
mümkün olduğunca az kez arayacaktır . Ama yine de, eğer çekirdek temeller yüklüyse, GNU ile de bulma araçlarına sahip find
olabilirsiniz -printf '%f\n'
ve aynı şeyi yapmak için kullanabilirsiniz .