Как вы используете регулярные выражения с командой cp в Linux?

22

Я пытаюсь скопировать только подмножество файлов из одного каталога в другой, используя, как cpбы то ни было, сообщение cp: cannot stat [^\.php]': No such file or directory. Есть ли способ использовать регулярные выражения только с помощью cpкоманды?

PeanutsMonkey
источник

Ответы:

29

Нет.

Команда cpне обладает способностью обрабатывать любые свои аргументы как регулярные выражения. Даже подстановочные знаки не обрабатываются им (или большинством исполняемых файлов); скорее они обрабатываются оболочкой.

cp test/* test2/фактически расширяется с помощью bash, и все, что на cpсамом деле видит его аргументы cp test/file1 test/file2 test/file3 test2/(или все, что подходит на основе фактического содержимого test/).

Кроме того, я не думаю, что ваше выражение [^\.php]будет соответствовать тому, что вы хотите (оно не соответствует только файлам, которые содержат .php).

Возможно, вы захотите заглянуть в findутилиту, чтобы отфильтровать список файлов по регулярному выражению, а затем использовать xargsдля применения возвращенного списка файлов к cpкоманде (предположим, что find не имеет встроенного обработчика для копирования файлов; I ' я не очень знаком с инструментом).

Вы можете попробовать:

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

Это говорит о необходимости рекурсивного поиска в текущем каталоге файлов, которые не содержат «.php» в пути, и копирования их в /destination/folder/.

В соответствии с просьбой, более конкретная разбивка аргументов:

  • . - Местоположение для начала поиска - в данном случае текущий каталог
  • ! - оператор "Не", инвертировать результат следующего теста
  • -iregex- Нечувствительный к регистру тест регулярных выражений. Следующий аргумент - это выражение.
  • ".*\.php.*"- Соответствие регулярному выражению <Anything>.php<Anything>- Любой файл, который имеет «.php» где-то в пути. (Обратите внимание, что, находясь внутри папки, в имени которой содержится «.php», вам понадобится более сложное выражение, чтобы соответствовать только файлам).
  • -exec- Выполните команду, если предыдущие тесты вернули true. Следующий аргумент - это команда, все оставшиеся аргументы ;передаются команде. {}это особый аргумент , представляющий имя файла.
  • cp - Команда find` должна запускаться на каждом из совпадающих путей.
  • {}- Путь к файлу, который был найден, передан cpв качестве аргумента, чтобы он знал, какой файл копировать
  • /destination/folder/- передан аргумент cp, указывающий, cpкуда следует скопировать файл.
  • \;- Это тот ;терминатор, который -execищет. Мы избегаем его с помощью \так, чтобы ваша оболочка не пыталась его проанализировать, а вместо этого подала его в качестве аргумента команды ( find)

Это довольно трудно написать регулярное выражение , которое соответствует «строке , которые не имеют .php», так что мы вместо того, чтобы сказать , findдля поиска строк , которые действительно содержат , .phpа затем инвертировать результаты с !.

Дарт Андроид
источник
2
find . -name [^\.php] -exec cp {} /path/to/location \;будьте осторожны с файлами со специальными символами.
Роб
@Dart Android - Спасибо. Я не знал об этом, cpи другие двоичные файлы не могли расширять регулярные выражения. Не могли бы вы уточнить, что означает каждый из вариантов и аргументов в приведенном вами примере? Я знаю , что .относится к текущей директории , но что делать !, {}, \;и т.д. см , а также то , что они означают? Например, почему вы должны избежать ;?
PeanutsMonkey
@Rob - Что вы подразумеваете под специальными файлами?
PeanutsMonkey
@Rob - я пытался схожим выражением удалить определенные файлы, но в итоге все файлы в каталоге были удалены. Моя команда была, find . -name '[^\.txt]' -exec rm {} \;следовательно, моим нежеланием пользоваться find. Вероятно, ошибка с моей стороны, но я не уверен, что я сделал не так. Насколько я понимаю, {}относится к каждому файлу, найденному командойfind . -name '[^\.txt]'
PeanutsMonkey
Что вы пытаетесь сопоставить с регулярным выражением?
Роб
10

Вы можете использовать несколько других инструментов из консоли, таких как grep и xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder
0xAF
источник
Как {}отличается от этого -t?
PeanutsMonkey
2
Не так много в этом случае. Альтернативный синтаксис для xargs будет «xargs cp {} destination_folder». Стандартный синтаксис cp принимает один или несколько источников и один пункт назначения в конце. Когда вы используете опцию -t, вы можете указать пункт назначения после -t, а затем использовать оставшуюся часть строки для источников. Я просто считаю, что опция -t более удобна в этом случае. В другом примере {} заменяется тем, что передается в xargs (stdin), в данном случае это имя файла.
0xAF
-1

Вы можете запустить следующую команду, простую в использовании:

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

круто хаа !!

Нисан чхетри
источник