Istnieją zasadniczo 2 metody, których można użyć do tego celu. Jeden parsuje ciąg, a drugi będzie działał na każdym pliku. Podczas analizowania ciągu użyj narzędzia takiego jak grep
, sed
lub, awk
oczywiście, będzie on szybszy, ale oto przykład pokazujący oba, a także sposób „profilowania” 2 metod.
Przykładowe dane
W poniższych przykładach wykorzystamy następujące dane
$ touch dir{1..3}/dir{100..112}/file{1..5}
$ touch dir{1..3}/dir{100..112}/nile{1..5}
$ touch dir{1..3}/dir{100..112}/knife{1..5}
Usuń niektóre *f*
pliki z dir1/*
:
$ rm dir1/dir10{0..2}/*f*
Podejście nr 1 - Analiza składni za pomocą łańcuchów
Tutaj mamy zamiar wykorzystywać następujące narzędzia, find
, grep
, i sort
.
$ find . -type f -name '*f*' | grep -o "\(.*\)/" | sort -u | head -5
./dir1/dir103/
./dir1/dir104/
./dir1/dir105/
./dir1/dir106/
./dir1/dir107/
Podejście nr 2 - Analiza przy użyciu plików
Ten sam łańcuch narzędzi jak poprzednio, tyle że tym razem będziemy używać dirname
zamiast grep
.
$ find . -type f -name '*f*' -exec dirname {} \; | sort -u | head -5
./dir1/dir103
./dir1/dir104
./dir1/dir105
./dir1/dir106
./dir1/dir107
UWAGA: Powyższe przykłady służą head -5
jedynie do ograniczenia ilości danych wyjściowych, z którymi mamy do czynienia w tych przykładach. Zwykle byłyby usuwane, aby uzyskać pełną listę!
Porównywanie wyników
Możemy użyć, time
aby spojrzeć na 2 podejścia.
dirname
real 0m0.372s
user 0m0.028s
sys 0m0.106s
grep
real 0m0.012s
user 0m0.009s
sys 0m0.007s
Dlatego zawsze najlepiej radzić sobie z ciągami znaków, jeśli to możliwe.
Alternatywne metody analizy ciągów
grep i PCRE
$ find . -type f -name '*f*' | grep -oP '^.*(?=/)' | sort -u
sed
$ find . -type f -name '*f*' | sed 's#/[^/]*$##' | sort -u
awk
$ find . -type f -name '*f*' | awk -F'/[^/]*$' '{print $1}' | sort -u
uniq
do miksu bardzo pomaga, usuwając powtarzające się linie, które są już obok siebie.find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'
. Lub jeśli twoje narzędzia są trochę starsze, to uniq może nie mieć opcji -z.find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u