Jak znaleźć pliki, a następnie przenieść je za pomocą xargs?


28

Chcę znaleźć jakieś pliki, a następnie je przenieść.

Mogę znaleźć plik za pomocą:

$ find /tmp/ -ctime -1 -name x*

Próbowałem przenieść je do mojego ~/playkatalogu za pomocą:

$ find /tmp/ -ctime -1 -name x* | xargs mv ~/play/

ale to nie zadziałało. Oczywiście mv potrzebuje dwóch argumentów.
Nie wiesz, czy (lub jak) odwoływać się do „bieżącego elementu” xargs w poleceniu mv?


3
Czemu? Można użyć zastępczy z -I: find . | xargs -I'{}' mv '{}' ~/play/, ale jak człowiek mówi, że „zakłada -xi -L 1”. Więc nie ma zysku. Lepiej, żeby było to proste i łatwe w użyciufind . -exec mv '{}' ~/play/ \;
manatwork

Prześlij jako odpowiedź, aby zobaczyć głosy, jeśli nie masz nic przeciwko :)
Michael Durrant

Właśnie zapytałem o powód, ponieważ miałem wrażenie, że nie mam sensu. Jeśli Drav Sloan doda notatkę o domyślnych opcjach, jego odpowiedź będzie tak dobra, jak najlepsza, jaką mogę napisać. Więc lepiej idź z tym.
manatwork

możliwy duplikat Znajdź wzór i przenieś
slm

@manatwork Zredagowałem swoją odpowiedź, aby odzwierciedlić te punkty, głupku :)
Drav Sloan

Odpowiedzi:


43

Spójrz na odpowiedź Stephane'a na najlepszą metodę, spójrz na moją odpowiedź z powodów, dla których nie używam bardziej oczywistych rozwiązań (i powodów, dla których nie są one najbardziej wydajne).

Możesz skorzystać z -Iopcji xargs:

find /tmp/ -ctime -1 -name "x*" | xargs -I '{}' mv '{}' ~/play/

Który działa w podobny sposób jak findi {}. Chciałbym również zacytować twój -nameargument (ponieważ plik zaczynający się xod bieżącego katalogu zostałby zarchiwizowany i przekazany jako argument do znalezienia - co nie zapewni oczekiwanego zachowania!).

Jednak, jak wskazano w manatwork, jak wyszczególniono na xargsstronie man:

   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with
          names read from standard input.  Also, unquoted  blanks  do  not
          terminate  input  items;  instead  the  separator is the newline
          character.  Implies -x and -L 1.

Należy zauważyć, że -L 1oznacza to, że przetwarzany będzie tylko jeden wiersz danych wyjściowych find. Oznacza to, że jest składniowo taki sam jak:

find /tmp/ -ctime -1 -name "x*" -exec mv '{}' ~/play/

(która wykonuje jedną mvoperację dla każdego pliku).

Nawet użycie -0argumentu GNU xargs i find -print0argument powoduje dokładnie takie samo zachowanie -I- dotyczy to clone()każdego pliku mv:

find . -name "x*" -print0 | strace xargs -0 -I '{}' mv '{}' /tmp/other

.
.
read(0, "./foobar1/xorgslsala11\0./foobar1"..., 4096) = 870
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =     0x7fbb82fad000
open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26066, ...}) = 0
mmap(NULL, 26066, PROT_READ, MAP_SHARED, 3, 0) = 0x7fbb82fa6000
close(3)                                = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 661
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 661
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 662
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 662
--- SIGCHLD (Child exited) @ 0 (0) ---
.
.
.

Zakłada się, że nazwy plików nie zawierają znaków nowej linii, pojedynczego cudzysłowu, podwójnego cudzysłowu ani odwrotnego ukośnika.
Stéphane Chazelas,

17

Za pomocą narzędzi GNU:

find /tmp/ -ctime -1 -name 'x*' -print0 |
  xargs -r0 mv -t ~/play/

Opcja -t( --target) jest specyficzna dla GNU. -print0, -r, -0, A nie standardowe i pochodzących z GNU występują również w niektórych innych implementacjach jak na niektórych BSD.

POSIXly:

find /tmp/ -ctime -1 -name 'x*' -exec sh -c '
  exec mv "$@" ~/play/' sh {} +

Oba uruchamiają tak mało mvpoleceń, jak to konieczne i działają niezależnie od znaków, jakie mogą zawierać nazwy plików. GNU jeden może mieć tę zaletę, że findszuka plików, gdy mvzaczyna przenosić pierwszą partię.

Uważaj, aby wszystkie pliki i katalogi znalazły się w jednym katalogu, uważaj na kolizje, jeśli kilka plików w różnych katalogach ma tę samą nazwę.


To rozwiązanie jest znacznie wydajniejsze, ponieważ wywołuje mvraz wszystkie argumenty (lub wszystkie -Llub -n, jeśli są dostarczone). W przeciwnym razie wywołanie mvkażdego pliku szybko się zestarzeje (i zwolni).
r2evans

1

Być może to polecenie jest teraz możliwe i nie było jeszcze w 2013 roku, ale działa to dla mnie idealnie:

ls pattern* | xargs mv -t DESTINATION/

Do -tkluczowych stawia folder docelowy pierwsze, zwalniając mvpolecenie, aby mieć wszystkie ostatnie argumenty jak tylko pliki mają być przeniesione.


1
to było najprostsze rozwiązanie, które zadziałało dla mnie
ptetteh227,

0

Możesz spróbować z poniższym poleceniem i przetestowane i działa dobrze

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
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.