9 Nisan 2020 Perşembe

find komutu exec seçeneği

Giriş
Açıklaması şöyle
Once you find some files or directories with the find command, you might want to do something for them. Thankfully, we can use the -exec option to run commands on each of the files or directories found. Any code after -exec will run on every file found.
exec seçeneğini kullanırken önce prova yapmak isteyebiliriz. Bu durumda komutun başına echo yazmamız yeterli.

Örnek
Şöyle yaparız. Böylece rm komutunun nasıl çalışacağı görülebilir.
find . type f -exec echo rm {} \;
1. \+ veya 
2. \; karakteri 

ile bitebilir. Açıklaması şöyle
Exec allows us to either pass all arguments at once with {} + or to pass them one by one with {} \;
1. \+ ile bitmesi - komuta çoklu parametre geçilir 
Açıklaması şöyle. -exec seçeneğinden sonra gelen komut mümkün olduğunca çok dosya ismi verilerek çalıştırılır yani her dosya için bir kere çalıştırılmaz.
This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files.  The command line is built in much the same way that xargs builds its command lines.
Örnek - yanlış kullanım
{} \+ arasında sadece boşluk (space) karakteri olabilir. Başka karakter giremez. Açıklaması şöyle
... there may be nothing between {} and + apart from whitespace. There is no way around that.
Dolayısıyla şu komut hata verir.
find . -name '*.png' -exec cp {} /tmp/dest \+
Örnek
exec ile çalıştırılan uygulamanın çıktısı başka uygulamaya geçilebilir. Şöyle yaparız,
Aslında cat a.txt b.txt c.txt | wc -l komutu ile aynıdır
find . -type f -exec cat {} \+ | wc -l
2. \; ile bitmesi - her parametre için komut bir kere daha çalıştırılır
-exec seçeneğinden sonra gelen komut için ayrı bir process yaratılır.
Örnek
Şöyle yaparız
find . -name "*.txt" -exec chown someOwner {} \;
Örnek
Bu komutun şu şekilde çalıştırılması riskli deniyor.
# risky
find -exec sh -c "something {}" \;
find -execdir sh -c "something {}" \;
Şu şekilde çalıştırmak daha güvenli deniyor ancak bu yöntemin pek kullanıldığını görmedim
# safer
find -exec sh -c 'something "$@"' sh {} \;
find -execdir sh -c 'something "$@"' sh {} \;
Örnek
copy için şöyle yaparız
find . -type f -newermt '16 july 2018' -exec cp {} /share/test \;
Örnek
move için şöyle yaparız
find src -name 'abc*' -type f -exec mv -nv {} dest/ \;
Eğer işlemden önce kullanılacak komutu görüp emin olmak istersek şöyle yaparız.
find src -name 'abc*' -type f -exec echo mv -nv {} dest/ \;
Örnek
Şöyle yaparız.
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec mv '{}' '{}'.new \;
Örnek
Dizin ismi ile dosya ismi aynı ise bunları bulmak için şöyle yaparız.
find . -type d -exec sh -c '
    for dirpath do
        filepath="$dirpath/${dirpath##*/}"
        [ -f "$filepath" ] && printf "%s\n" "$filepath"
    done' sh {} +
3. {} Kullanımı
 \+ veya \; ile geçilen parametreye erişmek için kullanılır

Örnek
Şöyle yaparız.
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec mv '{}' '{}'.new \;
4. $0 Kullanımı
Örnek - bash ile $0
Tüm results.txt dosyalarının ana dizinini ve dosyanın içini ekrana yazdırmak için şöyle yaparız.
$ find */ -name "result.txt" -exec bash -c 
  'printf "%s,%s\n" "${0%%/*}" "$(cat $0)"' {} \;
5. $1 Kullanımı
Örnek - 
bash ile $1
bash ile $1 kullanılabilir. Şöyle yaparız.
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec bash -c
  'cjpeg -quality 80 "$1" > "$(dirname "$1")/optimized_$(basename "$1")"' sh {} \;
Örnek
Şöyle yaparız. Burada file komutuna $1 ile dosya ismi geçiliyor. Dosya tipi PDF olanlar grep ile seçiliyor. 
find . -type f \
    -exec sh -c 'file "$1" | grep -q PDF' _ {} \;  \
    -exec sh -c 'echo mv -- "$1" "${1%%jpg}pdf"' _ {} \;
"_ {}" dizisinin açıklaması şöyle
_ {} is needed so that the contents of {} is assigned to $1 not $0
6. Komutun Sonucu
Başarısız olan uygulamaları görmek için şöyle yaparız
find . \! -exec yourscript {} \; -print

Hiç yorum yok:

Yorum Gönder