Jak używasz wyrażeń regularnych z komendą cp w systemie Linux?

22

Próbuję skopiować tylko podzbiór plików z jednego katalogu do drugiego przy użyciu cpwiadomości powitalnej cp: cannot stat [^\.php]': No such file or directory. Czy istnieje sposób używania wyrażeń regularnych tylko za pomocą cppolecenia?

PeanutsMonkey
źródło

Odpowiedzi:

29

Nie.

cpPolecenie nie posiadają zdolności do przetwarzania któregokolwiek z jej argumentów wyrażeń regularnych. Nawet symbole wieloznaczne nie są przez nią obsługiwane (lub większość plików wykonywalnych); raczej są obsługiwane przez powłokę.

cp test/* test2/jest w rzeczywistości rozszerzany przez bash, a wszystko, co cpnaprawdę widzi dla swoich argumentów, to cp test/file1 test/file2 test/file3 test2/(lub cokolwiek jest właściwe w oparciu o rzeczywistą zawartość test/).

Ponadto, nie sądzę, aby twoje wyrażenie [^\.php]pasowało do tego, czego chcesz (nie pasuje tylko do plików, które zawierają .php).

Prawdopodobnie chcesz zajrzeć do findnarzędzia, aby odfiltrować listę plików na podstawie wyrażeń regularnych, a następnie użyć, xargsaby zastosować listę plików zwróconych do cppolecenia (zakładając, że find nie ma wbudowanego modułu do kopiowania plików; I ' nie jestem do końca zaznajomiony z narzędziem).

Możesz spróbować:

find . ! -iregex ".*\.php.*" -exec cp {} /destination/folder/ \;

Mówi to, aby przeszukiwać bieżący katalog rekurencyjnie w poszukiwaniu plików, które nie zawierają „.php” w ścieżce i kopiować je /destination/folder/.

Zgodnie z życzeniem, bardziej szczegółowy podział argumentów:

  • . - Lokalizacja, aby rozpocząć wyszukiwanie - w tym przypadku bieżący katalog
  • ! - Operator „Not”, odwróć wynik następnego testu
  • -iregex- Test wyrażeń regularnych bez rozróżniania wielkości liter. Następnym argumentem jest wyrażenie.
  • ".*\.php.*"- Dopasowywanie wyrażeń regularnych <Anything>.php<Anything>- Dowolny plik z „.php” gdzieś na ścieżce. (Uwaga: w tym w folderze, który zawiera w nazwie „.php”, potrzebujesz bardziej złożonego wyrażenia, aby dopasować tylko pliki)
  • -exec- Wykonaj polecenie, jeśli poprzednie testy zwrócą wartość true. Kolejnym argumentem jest polecenie, wszystkie pozostałe argumenty do ;są przekazywane do polecenia. {}jest specjalny argument, reprezentujący nazwę.
  • cp - Polecenie find` powinno działać na każdej z pasujących nazw ścieżek.
  • {}- Ścieżka do znalezionego pliku przekazana cpjako argument, aby wiedział, który plik skopiować
  • /destination/folder/- przekazano argument do cp, cpgdzie należy skopiować plik.
  • \;- To jest ;terminator, którego -execszuka. Uciekamy od niego \, aby twoja powłoka nie próbowała go parsować i zamiast tego podaje go jako argument do polecenia ( find)

To raczej trudno napisać wyrażenie regularne, które pasuje „ciągi, które nie mają .php”, więc zamiast powiedzieć find, aby szukać łańcuchów, które nie zawierają .php, a następnie odwrócić z wynikami !.

Darth Android
źródło
2
find . -name [^\.php] -exec cp {} /path/to/location \;uważaj na pliki ze znakami specjalnymi.
Rob
@Darth Android - Dzięki. Nie wiedziałem, że cpi inne pliki binarne nie były w stanie rozwinąć wyrażeń regularnych. Czy mógłbyś opracować, co oznaczają poszczególne opcje i argumenty w podanym przykładzie? Wiem, że .odnosi się do aktualnego katalogu, ale czego !, {}, \;itp znajdują się także co one oznaczają? Na przykład dlaczego musisz uciec ;?
PeanutsMonkey,
@Rob - Co rozumiesz przez specjalne pliki?
PeanutsMonkey,
@Rob - Podjąłem podobne wyrażenie, aby usunąć określone pliki, jednak skończyło się to usunięciem wszystkich plików w katalogu. find . -name '[^\.txt]' -exec rm {} \;Stąd moja rozkaz polegała na niechęci do używania find. Prawdopodobnie błąd z mojej strony, ale nie jestem pewien, co zrobiłem źle. O ile rozumiem, {}odnosi się do każdego pliku znalezionego przez poleceniefind . -name '[^\.txt]'
PeanutsMonkey,
Co próbujesz dopasować do wyrażenia regularnego?
Rob
10

Możesz użyć kilku innych narzędzi z konsoli, takich jak grep i xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder
0xAF
źródło
Czym {}różni się od tego -t?
PeanutsMonkey
2
W tym przypadku niewiele. Alternatywna składnia dla xargs to „xargs cp {} folder_docelowy”. standardowa składnia cp pobiera na końcu jedno lub wiele źródeł i jedno miejsce docelowe, gdy używasz opcji -t, możesz określić miejsce docelowe po -t, a następnie użyć reszty wiersza dla źródeł. Po prostu uznaję opcję -t w tym przypadku za wygodniejszą. W innym przykładzie {} jest zastąpione przez to, co jest przesyłane do xargs (stdin), w tym przypadku nazwę pliku.
0xAF,
-1

Możesz uruchomić następujące polecenie łatwe w użyciu:

find /home/usr/search_dir -iname *file_name_portion*.txt | xargs cp -t /home/usr/destination_folder

spoko haa !!

Nisan Chhetri
źródło