Uzak dizinde en son değiştirilen dosyayı SCP


0

Uzaktaki bir ana bilgisayardaki bir dizindeki en son değiştirilen dosya SCP'ye basit bir komut var mı? Bunun yerelden uzak bir noktaya nasıl yapıldığını çözebilirim ... scp ``ls -Art | tail -n 1\`` usr@remote:/var/log/yeet Aynı şeyi nasıl yapabilirim ama uzaktan kumandadan lokalize. (Bu nedenle, en son değiştirilen dosyayı yeet'ten alın ve yerel ana bilgisayara kopyalayın)

Yanıtlar:


0

Burada birkaç sorun var.

ayrıştırma ls

Her şeyden önce ayrıştırmamalı ls. Sizin ls -Art | tail -n 1 kusurludur ve güvenilir bir şekilde sabitlenemez. Standart bir güvenilir değiştirme find ve / veya boş sonlandırılmış çizgilerle çalışma.

Ayrıca, en son değiştirilen dosyaya (bir dizin değil) doğrudan geçerli dizinde (bir alt dizinde değil) ihtiyacınız olduğunu varsayıyorum.

Girdi öğelerini boş sonlandırılmış liste biçiminde ayrıştırma yeteneği genellikle POSIX tarafından gerekli değildir. Araçlarınız seçeneklerle yeterince zenginse, bu sizin cihazınız için sağlam bir yerine ls -Art | tail -n 1:

find . -maxdepth 1 -type f -printf '%T@ %p\0' |
   sort -zrn |
   head -zn 1 |
   cut -z -d " " -f 2-

Sonucu boş bırakılmış bir dosya adı olarak verir. Onunla bir şeyler yapmak için onu xargs -0 …, Örneğin.:

… | xargs -0r cp -t "/target/dir/" --

veya (eğer cp desteklemiyor -t ):

… | xargs -0r -I {} cp -- {} "/target/dir/"

Bu komutlarda POSIX'in gerektirmediği birçok şey vardır (bu nedenle taşınabilir değildir). -- hangi yapar cp seçenekler için ayrıştırmayı durdurun, ör. bir dosya -R kopyalanmak yerine özyinelemeyi tetiklemeyecektir. Unutmayın ki dosya isimlerimiz find . … ile başlar . elbette -- güvenle atlanabilir. Ben sadece uğraşırken iyi bir genel uygulama işaret etmek için kullandım cp. Başka bir iyi uygulama yolları alıntı yapmaktır: değişmez /target/dir/ tırnak işaretleri olmadan çalışırdı, ancak bu örneği kendi hedef yolunuzla değiştirdikten sonra, alıntılara ihtiyacınız olabilir, bu yüzden yine de kullanıyorum.

(Yerelden uzaklara) durumunuzda kullanırdınız scp yerine cp. Argümanları ayrıştırırken kendi tuhaflıkları olabilir.

POSIX uyumlu ancak düşük performanslı bir komut olabilir:

find . ! -name . -prune -type f -exec sh -c '
   [ "$(find . ! -name . -prune -type f -newer "$1" -exec printf a \; |
   wc -c)" -eq 0 ]' sh {} \; -print

Bir yaklaşımı uyarlar bu başka bir cevap yerine koymak (POSIX dışı) -maxdepth 1. Yumurtlar sh güvenilir bir şekilde yuva iki find … -exec … maddeleri . Dış find tüm dosyaları inceler ve onları birer birer içsel besler. find. İç find Tüm dosyaları verilen dosyadan daha yeni bulur, tek bir karakter basar ( a ) her yeni dosya için. wc -c bu karakterleri sayar. Hiçbiri yoksa, verilen dosyanın en son değiştirildiği anlamına gelir; sadece o zaman dış find yazdırır.

Dış ne zaman birkaç senaryo var find birden fazla dosya yazdırabilir:

  • Aynı "en yeni" zamanı olan iki veya daha fazla dosya var;
  • dizindeki dosyalar komut çalışırken değiştirilir;
  • find bazı dosyaları statüre edemiyorum.

Bu yüzden -quit dış son eylem olarak find yararlı olurdu (iç için yararlı olacağını unutmayın) find de, ama farklı bir nedenden dolayı). ne yazık ki -quit POSIX değil.

kullandım -print ( -print0 POSIX değildir), yine de standart olmayan dosya isimleri problem değildir çünkü çıktıyı başka bir komuta yönlendirmeniz gerekmez. Sadece kullan -exec bu mümkün olan tüm dosya isimleriyle ilgilidir; Örneğin. yerine -print kullan:

-exec yet_another_command {} \;

Artık en son değiştirilen dosyayı yerel bir dizinde nasıl ayrıştırmayacağınızı biliyorsunuz ls.

Uzak bir sistemdeki dosyaları bulma

Hangi yaklaşımı seçerseniz seçin (kusurlu dahil) ls … | tail … istediğiniz dosyayı uzak bir dizinde bulabilmek için komutu uzak sistemde çalıştırmanız gerekir (ya da sonra bu istisnaya ulaşacağım).

En açık yaklaşım ssh uzaktaki sisteme Yeni bağlamda, uzaktaki sistem yereldir ve yerel bilgisayarınız uzaktır. (Burada örnek olarak yukarıdaki POSIX uyumlu komutu kullanıyorum, ancak ilkimizi kullanabilirsiniz. find … | sort -z … | head -z … | cut -z … | xargs -0 … sadece uzaktaki sistem gerekli tüm seçenekleri destekliyorsa).

ssh usr@remote
# now on the remote system
cd "/source/dir/" &&
find . ! -name . -prune -type f -exec sh -c '
   [ "$(find . ! -name . -prune -type f -newer "$1" -exec printf a \; |
   wc -c)" -eq 0 ]' sh {} \; -exec scp {} usr@local:"/target/dir/" \;

Sakınmak istiyorsanız not alın cd ve kullan find /source/dir … o zaman dahası var . -s ile değiştirilmesi gereken /source/dir. İle daha kolay cd.

Yerel sisteminize, uzaktan kumandadan SSH ile erişebilmek için ihtiyacınız var. Yolda NAT varsa, bunun gibi bir uzak bağlantı noktası iletme ile atlayabilirsiniz:

ssh -R 12322:127.0.0.1:22 usr@remote
# now on the remote system the same cd + find as above
# only the scp part is different 
… -exec scp -P 12322 {} usr@127.0.0.1:"/target/dir/" \;

Uzak bağlantı noktasını yaptığını unutmayın. 12322 bulunduğunuz bölgeye yönlendirin sshd ve uzaktaki sistemin herhangi bir kullanıcısı, onu kötüye kullanmaya çalışabilir. Başka bir sorun: Uzaktaki sistem bir portu ilk başta yönlendirmenize izin vermeyecek şekilde yapılandırılmış olabilir.

Yerel sistemde çağırmak için tek bir komut isteyebilirsiniz. Bu durumda uygun bir alıntı yapılması gerekir ve daha da hantal hale gelir:

ssh usr@remote '
   cd "/source/dir/" &&
   find . ! -name . -prune -type f -exec sh -c '"'"'
      [ "$(find . ! -name . -prune -type f -newer "$1" -exec printf a \; |
      wc -c)" -eq 0 ]'"'"' sh {} \; -exec scp {} usr@local:"/target/dir/" \;
   '

Uzaktan eğer sorun bekliyorum scp Yine de şifrenizi sormanız gerekiyor. Bu nedenle ya da yerel bölgenize koşamıyor / ulaşamıyorsanız sshd, başka bir yaklaşıma ihtiyacınız olabilir.

Bu yerel komut uzak sistemden elde edilen istenen dosya adını yazdıracaktır:

ssh usr@remote '
   cd "/source/dir/" &&
   find . ! -name . -prune -type f -exec sh -c '"'"'
      [ "$(find . ! -name . -prune -type f -newer "$1" -exec printf a \; |
      wc -c)" -eq 0 ]'"'"' sh {} \; -print
   '

İle kullanabilirsiniz yerel gibi araçlar xargs ve scp. Ne ayrıştırma olduğunu unutmayın -print verim ayrıştırmadan sadece biraz daha iyidir ls. kullanım -print0 (POSIX dışı, mevcut olmayabilir) veya -exec printf "%s\0" {} \; yerine (çalışması gerekir) -print İstenilen dosya adını boş sonlandırılmış bir dize olarak elde etmek için. Şimdi yerel tarafta onunla ne yapacağınız size kalmış. POSIX uyumlu bir uzaktan kumandaya ihtiyacınız varsa ancak yerel sisteminizdeki araçlar seçenek bakımından zenginse bu özellik faydalıdır.

Önemli istisna: sshfs

sshfs monte etmenizi sağlar usr@remote:"/source/dir/" olarak /local/path/. Görmek bu cevabım benim , Tüm detayları ele almak için kendimi tekrar etmeyeceğim. Senin durumunda zengin (POSIX ile sınırlı değil) araçlarını içeren (yerel) prosedür:

sshfs usr@remote:"/source/dir/" "/local/path/"
find "/local/path/" -maxdepth 1 -type f -printf '%T@ %p\0' |
   sort -zrn |
   head -zn 1 |
   cut -z -d " " -f 2- |
   xargs -0r cp -t "/target/dir/" --
fusermount -u "/local/path/"

Bu harika. Yaptığın her şey yerel araçlar. Eğer sadece sen kullanabilirsen sshfs uzak taraftaki aletler ve mevcut seçenekleri artık önemli değil. Yerel sisteminize dışarıdan ulaşıp ulaşamayacağınız da önemli değil. Ve yöntem aynıdır: uzaktaki yerel veya uzaktaki yerel, uzak önemli değil.

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.