Usuń ścieżkę z danych wyjściowych polecenia find


29

Mam skrypt bash do wdrażania kodu ze środowiska beta do środowiska produkcyjnego, ale obecnie muszę ręcznie dodać listę plików do pliku txt, a czasem brakuje. Zasadniczo mój skrypt instalacyjny cat / pętle kopiuje pliki. (eksportuje / importuje również db, ale to nie dotyczy .. lol)

W każdym razie chciałbym użyć findpolecenia do wygenerowania listy plików zmodyfikowanych w ciągu ostatnich 14 dni. Problem polega na tym, że muszę usunąć ścieżkę, ./aby skrypt wdrażania działał.

Oto przykład użycia polecenia find:

odnaleźć . -type f -mtime -14> deploy.txt

Oto wiersz, który koty deploy.txtw moim skrypcie wdrażania:

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

Masz pomysł, jak to osiągnąć za pomocą skryptów bash?

Dzięki!


3
Czy istnieje powód, dla którego nie można po prostu użyć do tego programu rsync? Brzmi, jakbyś próbował odkryć koło i zrobić z niego trójkąta.
ThatGraemeGuy

ważny punkt jednak przed wdrożeniem plik deploy.txt jest sprawdzany i usuwane jest wszystko, co wymaga naprawy
Mikey1980,

1
Może uruchom rsync w --dry-runtrybie i wyślij go do pliku w celu przejrzenia?
Zoredache

Odpowiedzi:


36

Możesz użyć -printfopcji wiersza polecenia, %faby wydrukować tylko nazwę pliku bez żadnych informacji katalogowych

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

lub możesz użyć sed, aby usunąć ./

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

Wierzę, że musisz uciec /..
EEAA

5
Nie, gdy używasz |jako separatora.
user9517 obsługuje GoFundMonica

3
Użycie %fspowoduje usunięcie wszystkich katalogów, nie tylko ./. Spowoduje to uszkodzenie jego skryptu wdrażania, jeśli którykolwiek z zwracanych plików findznajdzie się w podkatalogach.
James Sneeringer

2
@Ind Musisz jednak uciec .. A może najlepiej użyć kotwicy początkowej:s|^\./||
James O'Gorman

12
Użyj %Pzamiast %f. To po prostu odcięło ścieżkę podaną w wierszu poleceń.
TrueY

11

./Powinny być nieszkodliwe. Większość programów będzie traktować /foo/bari /foo/./barjako równoważne. Zdaję sobie sprawę, że nie wygląda to zbyt ładnie, ale na podstawie tego, co opublikowałeś, nie widzę powodu, dla którego miałby spowodować awarię skryptu.

Jeśli naprawdę chcesz go zdjąć, sedto prawdopodobnie najczystszy sposób:

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

Jeśli korzystasz z systemu z GNU find (np. Większość systemów Linux), możesz to zrobić jednym strzałem find -printf:

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

Te %Ppowroty pełna ścieżka każdego pliku znaleziony, minus ścieżka podana w wierszu poleceń, włącznie pierwszy ukośnik. Pozwoli to zachować wszystkie podkatalogi w strukturze katalogów.


1
./Prefiks jest właściwie cechą; bez niego przesyłanie danych wyjściowych do innych poleceń nie będzie działać poprawnie, np. w przypadku nazw plików rozpoczynających się od myślnika.
tripleee

1
@tripleee - Rozumiem użyteczność tego, ale OP specjalnie zapytał, jak go usunąć, ponieważ powodował problemy w jego skrypcie instalacyjnym. Jasne, mogą istnieć lepsze sposoby robienia tego, co powinien, ale to jest królicza nora znacznie wykraczająca poza zakres tego, o co pytano.
James Sneeringer,

7

Dlaczego musisz się rozebrać ./? Ważne jest, aby mieć na ścieżce. Więc

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

jest w porządku!

Ale jeśli chcesz usunąć nazwę katalogu w find, możesz użyć %Pargumentu do -printf.

man find (1) mówi:

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

Przykład

$ 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

Uważaj na pierwszą pustą linię! Jeśli chcesz tego uniknąć, użyj-mindepth 1

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

3

Masz kilka opcji. Możesz użyć -printfopcji znajdowania, aby wydrukować tylko nazwę pliku, lub możesz użyć narzędzia takiego jak sed, aby po prostu usunąć plik ./.

# 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/^\.\///'

Czy możesz podać mi przykład jego użycia? Niestety, Linux nie jest tak naprawdę moim fortecą
Mikey1980,

2
Spójrz jeszcze raz, są przykłady.
Zoredache

Zgadzam się - po prostu spróbuj, nic nie skrzywdzisz, używając kombinacji find i sed.
EEAA

3

Rozwiązanie „find -printf” nie będzie działać na FreeBSD, ponieważ find nie ma takiej opcji. W takim przypadku AWK może pomóc. Zwraca nazwisko ($ NF), dzięki czemu może pracować na dowolnej głębokości.

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

PS: zaczerpnięte z książki D.Tansleya „Programowanie powłoki Linuksa i Uniksa”


2

Szybkim rozwiązaniem, jeśli dobrze rozumiem pytanie, jest użycie cutdanych wyjściowych findpolecenia:

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

Spowoduje to usunięcie pierwszych znaków z każdej linii wyniku (w twoim przypadku ./). Prawdopodobnie nie najlepsze rozwiązanie, ale działa w twoim scenariuszu.


1

sed jest idealny do tego rodzaju rzeczy.

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

1

Nie wiem, o jakich nazwach plików mówimy, ale cokolwiek ze spacjami lub znakami nowej linii naraża większość rozwiązań tutaj.

Moją sugestią byłoby użycie rozszerzenia parametrów powłoki do usuwania znaków z każdej nazwy pliku:

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

Jeśli naprawdę lubisz potoki, możesz użyć „bezpiecznego” separatora, np. Null, z xargs do otrzymania każdej nazwy pliku:

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

Pamiętaj, że wynik tego NIE jest rozdzielany wartością zerową, więc chociaż może być wystarczający do sprawdzenia gałki ocznej, żadne z tych rozwiązań nie tworzy pliku deploy.txt, który można bezpiecznie wykorzystać do automatyzacji, chyba że masz pewność co do źródła nazwy plików.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.