Find komut çıktısından yolu kaldır


29

Bir beta ortamından bir üretim ortamına kod dağıtmak için bir bash betiğim var ancak şu anda dosyaların listesini bir txt dosyasına manaully olarak eklemeliyim ve bazen bazılarını özlüyorum. Temelde dağıtım komut dosyası, dosyaların kopyalanmasını engelliyor. (ihracat / ithalat db de ama bu konuyla ilgili değil ... lol)

Neyse, findson 14 günde değiştirilen dosyaların bir listesini oluşturmak için bu komutu kullanmak istiyorum . Sorun, ./dağıtım komut dosyasının çalışabilmesi için yolu çıkarmam gerekiyor.

İşte find komutu kullanımına bir örnek:

Bul -tipi f -mtime -14> deploy.txt

İşte deploy.txtdağıtım betiğimdeki kedilerin sayısı :

for i in `cat deploy.txt`; do cp -i /home/user/beta/public_html/$i /home/user/public_html/$i; done

Bash komut dosyası kullanarak bu başarmak için herhangi bir fikir?

Teşekkürler!


3
Bunun için sadece rsync kullanamamanızın bir nedeni var mı? Tekerleği yeniden icat etmeye ve bir üçgen haline getirmeye çalışıyor olabilirsiniz.
ThatGraemeGuy

ancak dağıtımdan önce geçerli olan nokta deploy.txt gözden geçirilir ve düzeltilmesi gereken her şey kaldırılır
Mikey1980

1
Belki --dry-runmodunda rsync çalıştırın ve bu dosyayı incelemek için bir dosyaya çıktı?
Zoredache

Yanıtlar:


36

Herhangi bir dizin bilgisi olmadan sadece dosya adını yazdırmak için -printfkomut satırı seçeneğini kullanabilirsiniz.%f

find . -type f -mtime -14 -printf '%f\n' > deploy.txt

veya sadece kaldırmak için sed kullanabilirsiniz.

find . -type f -mtime -14 | sed 's|^./||' >deploy.txt

Kaçman gerektiğine inanıyorum /..
AÇAA

5
|Sınırlayıcı olarak kullandığınızda olmaz .
user9517

3
Kullanmak %f, yalnızca dizinleri değil tüm dizinleri kaldıracaktır ./. Bu, döndürülen dosyalardan herhangi birinin findalt dizinlerde yer alması durumunda, dağıtım komut dosyasını kıracak .
James Sneeringer

2
@Iain Yine de kaçman gerekiyor .. Ve belki de en iyisi bir başlangıç ​​ankrajı kullanmaktır:s|^\./||
James O'Gorman,

12
Yerine %Pkullanın %f. Bu sadece komut satırında verilen yolu keser.
TrueY

11

./Zararsız olmalıdır. Çoğu program davranacak /foo/barve /foo/./bareşdeğer. Çok hoş görünmediğini fark ettim, ancak gönderdiklerinize bağlı olarak, senaryonuzun başarısız olmasına neden olacak hiçbir neden göremiyorum.

Gerçekten çıkarmak istiyorsan sed, muhtemelen en temiz yol:

find . -type d -mtime 14 | sed -e 's,^\./,,' > deploy.txt

GNU bul bulunan bir sistemdeyseniz (örneğin çoğu Linux sistemi), tek seferde şunu yapabilirsiniz find -printf:

find . -type d -mtime 14 -printf "%P\n" > deploy.txt

%PDöner her dosyanın tam yolu bulunamadı, eksi yol kadar ve ilk eğik çizgi dahil komut satırında belirtilmiş. Bu, dizin yapınızdaki tüm alt dizinleri koruyacaktır.


1
./Önek aslında bir özelliktir; onsuz, diğer komutlara boru çıkışı düzgün bir şekilde çalışmaz, örneğin kısa çizgi ile başlayan dosya adları için.
üçlü

1
@tripleee - Faydasını anlıyorum, ancak OP özellikle dağıtım komut dosyası için sorunlara neden olduğu için nasıl sıyrılacağını sordu. Tabii ki, yapması gerekeni yapmanın daha iyi yolları olabilir, ama bu sorulanın kapsamının çok ötesinde bir tavşan deliği.
James Sneeringer

7

Neden sıyrılmaya ihtiyacın var ./? Bir yolda olması geçerli. Yani

cp -i dir1/./somefile dir2/./somefile

tamamdır!

Fakat dizin içindeki dizini çıkarmak istiyorsanız %Pargümanını kullanabilirsiniz -printf.

adam bulmak (1) diyor:

         %P     File's name with the name of the  command  line  argument
                 under which it was found removed.

Bir örnek

$ find other -maxdepth 1
other
other/CVS
other/bin
other/lib
other/doc
other/gdbinit
$ find other -maxdepth 1 -printf "%P\n"

CVS
bin
lib
doc
gdbinit

İlk boş satıra dikkat et! Kullanmaktan kaçınmak istiyorsanız-mindepth 1

$ find other -mindepth 1 -maxdepth 1 -printf "%P\n"
CVS
bin
lib
doc
gdbinit

3

Peki, birkaç seçeneğin var. -printfYalnızca dosya adını yazdırmak için bulma seçeneğini kullanabilirsiniz veya basitçe çıkarmak için sed gibi bir araç kullanabilirsiniz ./.

# simply print out the filename, will break if you have sub-directories.
find . -mtime -14 -printf '%f\n'

# strip a leading ./
find .  -mtime -14 | sed -e 's/^\.\///'

Kullanımına bir örnek verebilir misiniz? Üzgünüz, linux gerçekten benim kalem değil
Mikey1980

2
Tekrar bak, örnekler var.
Zoredache

Anlaştık - sadece dene, bul ve sed kombinasyonunu çalıştıran hiçbir şeyi incitmeyeceksin.
AÇAA

3

"find -printf" çözümü, FreeBSD üzerinde çalışmaz, çünkü böyle bir seçenek bulunmaz. Bu durumda AWK yardımcı olabilir. Soyadı (NF $) döndürür, böylece herhangi bir derinlikte çalışabilir.

find /usr/local/etc/rc.d -type f | awk -F/ '{print $NF}'

Not: D.Tansley "Linux ve Unix kabuk programlama" kitabından alınmıştır.


2

Soruyu doğru anlarsam, hızlı bir çözüm komutun cutçıktısını kullanıyor find:

$> find . -type f -mtime -14 | cut -b 3- > deploy.txt

Bu, sonucun her satırındaki karakterlerden ilkini sıyırır (sizin durumunuzda ./). Muhtemelen en iyi çözüm değil, senaryoda çalışıyor.


1

sed bu tür şeyler için mükemmel.

$ find . -type f -mtime -14 find . | sed 's/^\.\///' > deploy.txt

1

Ne tür bir dosya adından bahsettiğimizi bilmiyorum, ancak boşluk veya yeni satır içeren herhangi bir şey, çözümlerin çoğunu tehlikeye atıyor.

Önerim, her dosya adındaki karakterleri silmek için shell'in parametre genişletmesini kullanmak olacaktır:

find . -mtime -14 -exec sh -c 'printf "${0#./}\n"' {} \; >deploy.txt

Eğer boruları gerçekten seviyorsanız, her dosya adını almak için boş olan bir "güvenli" sınırlayıcı kullanabilirsiniz.

find . -mtime -14 -print0 | xargs -0 -n 1 sh -c 'printf "${0#./}\n"' >deploy.txt

Bu çıkış olduğunu unutmayın DEĞİL size kaynağı hakkında çok emin olmadıkça bir göz küresi kontrolü için yeterli olabilir iken, yani boş ayrılmış, bu çözümlerin hiçbiri, otomasyonu için kullanmak güvenli bir deploy.txt dosyası üretmek dosya.

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.