Jestem w stanie zlokalizować pliki w folderze zawierającym określony ciąg tekstowy za pomocą tego polecenia:
grep -lir 'string' ~/directory/*
Jak przenieść pliki z powyższego wyniku do innej lokalizacji?
Jestem w stanie zlokalizować pliki w folderze zawierającym określony ciąg tekstowy za pomocą tego polecenia:
grep -lir 'string' ~/directory/*
Jak przenieść pliki z powyższego wyniku do innej lokalizacji?
Odpowiedzi:
Jak zawsze, uważaj grep -r. -rnie jest standardową opcją, a w niektórych implementacjach, takich jak wszystkie oprócz najnowszych wersji GNU grep, podąża za dowiązaniami symbolicznymi podczas schodzenia z drzewa katalogów, co na ogół nie jest tym, czego chcesz i może mieć poważne konsekwencje, jeśli na przykład istnieje dowiązanie symboliczne do „/ „gdzieś w drzewie katalogów.
W filozofii uniksowej używasz polecenia do przeszukiwania katalogów w poszukiwaniu plików, a drugiego do przeglądania jego zawartości.
Korzystając z narzędzi GNU, zrobiłbym:
xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
) mv -i --target-directory /dest/dir
Ale nawet wtedy uważaj na warunki wyścigu i możliwe problemy z bezpieczeństwem, jeśli uruchomisz go jako jeden użytkownik w katalogu, który może zapisać inny użytkownik.
xargsprzed przeczytaniem do końca pliku arg, co nie powinno się zdarzyć, chyba że xargs zostanie zabity sam lub zawiedzie z jakiegokolwiek powodu, w takim przypadku spodziewam się, że również zobaczysz błąd.
Użyj xargsw połączeniu z mvtrzecią składnią:mv [OPTION]... -t DIRECTORY SOURCE...
grep -lir 'string' ~/directory/* | xargs mv -t DEST
Uważaj na pliki zawierające znaki specjalne (spacje, cudzysłowy). W takim przypadku filtrowanie listy za pomocą sed(dodawanie cudzysłowów wokół nazw plików za pomocą s/^/'/;s/$/'/) może pomóc, ale musisz mieć pewność, że te cytaty nie pojawią się w nazwach plików. GNU grepma opcję -Z/ --null, aby zakończyć nazwy plików na NUL.
Alternatywą dla trzeciej składni mvjest użycie xargsz symbolem zastępczym string ( -I).
Inną opcją jest podstawianie poleceń - $( )lub backsticks ``(w bash), jak wspomniano w odpowiedzi ire_and_curses.
Jeśli nazwy plików nie zawierają żadnych znaków specjalnych (białe znaki lub \[*?), użyj podstawienia polecenia :
mv `grep -lir 'string' ~/directory/*` destination/
Używając tylko określonych funkcji POSIX i nie przyjmując żadnych założeń dotyczących nazw plików:
find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;
Uwagi:
Powiedziałeś „ciąg” nie „wzorzec”, więc -Fopcja (naprawione wyszukiwanie ciągów) grepwydaje się odpowiednia.
Jeśli katalog docelowy znajduje się w dowolnym miejscu w katalogu wyszukiwania, możesz mieć nieprzyjemne warunki wyścigu.
Używanie GNU równoległego :
grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'
ht / @ lin-dong za oryginalną odpowiedź na xargs.
-Załóż, że masz katalog docelowy jako „zewnętrzny” i musisz przenieść wszystkie pliki XLS, możesz wypróbować poniższe polecenie
sudo mv find /var/log/ -type f -name "*.xls"/ external /
grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name