Comment utilisez-vous les expressions régulières avec la commande cp sous Linux?

22

J'essaie de copier uniquement un sous-ensemble de fichiers d'un répertoire à un autre en utilisant cpcependant je suis accueilli par le message cp: cannot stat [^\.php]': No such file or directory. Existe-t-il un moyen d'utiliser des expressions régulières uniquement à l'aide de la cpcommande?

PeanutsMonkey
la source

Réponses:

29

Non.

La cpcommande ne possède la capacité de traiter aucun de ses arguments comme des expressions régulières. Même les caractères génériques ne sont pas gérés par lui (ou la plupart des exécutables); ils sont plutôt gérés par le shell.

cp test/* test2/est en fait développé par bash, et tout ce cpqui voit vraiment pour ses arguments sont cp test/file1 test/file2 test/file3 test2/(ou tout ce qui est approprié en fonction du contenu réel de test/).

De plus, je ne pense pas que votre expression, [^\.php]correspondra à ce que vous voulez (elle ne correspond pas uniquement aux fichiers qui contiennent .php).

Vous souhaitez probablement examiner l' findutilitaire pour filtrer une liste de fichiers basée sur une expression régulière, puis utiliser xargspour appliquer la liste de fichiers renvoyée à la cpcommande (en supposant que find n'a pas de gestionnaire intégré pour copier des fichiers; je '' Je ne connais pas intimement l'outil).

Vous pourriez essayer:

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

Cela dit de rechercher récursivement dans le répertoire courant les fichiers qui ne contiennent pas ".php" dans le chemin et de les copier /destination/folder/.

Comme demandé, une ventilation plus spécifique des arguments:

  • . - Emplacement pour démarrer la recherche - dans ce cas, le répertoire courant
  • ! - Opérateur "Non", inverser le résultat du prochain test
  • -iregex- Test d'expression régulière insensible à la casse. L'argument suivant est l'expression.
  • ".*\.php.*"- Correspondance d'expressions régulières <Anything>.php<Anything>- Tout fichier contenant ".php" quelque part dans le chemin. (Remarque, y compris dans un dossier contenant ".php" dans le nom, vous auriez besoin d'une expression plus complexe pour ne faire correspondre que les fichiers)
  • -exec- Exécutez une commande si les tests précédents renvoient true. L'argument suivant est la commande, tous les arguments restants jusqu'à ;sont passés à la commande. l' {}argument est spécial représentant le nom du fichier.
  • cp - La commande qui trouve` doit s'exécuter sur chacun des noms de chemin correspondants.
  • {}- Le chemin vers le fichier trouvé, passé cpen argument pour qu'il sache quel fichier copier
  • /destination/folder/- argument passé à cp, indiquant cpoù il doit copier le fichier.
  • \;- C'est le ;terminateur -execrecherché. Nous l'échappons avec un \afin que votre shell n'essaye pas de l'analyser et le nourrit à la place comme argument de la commande ( find)

Il est assez difficile d'écrire une expression régulière qui correspond à « des chaînes qui ne sont pas .php», donc nous disons au lieu findde rechercher des chaînes qui ne contiennent .php, puis inverser les résultats avec !.

Dark Android
la source
2
find . -name [^\.php] -exec cp {} /path/to/location \;attention aux fichiers avec des caractères spéciaux.
Rob
@ Dark Android - Merci. Je n'étais pas au courant de cela cpet d'autres binaires n'étaient pas en mesure d'étendre les expressions régulières. Pourriez-vous élaborer ce que chacune des options et arguments signifie dans l'exemple d'exemple que vous avez donné? Je sais que .fait référence au répertoire courant , mais qu'est-ce que !, {}, \;, etc décrirais comme bien ce qu'ils veulent dire? Par exemple, pourquoi devez-vous échapper au ;?
PeanutsMonkey
@Rob - Qu'entendez-vous par fichiers spéciaux?
PeanutsMonkey
@Rob - J'ai tenté une expression similaire pour supprimer des fichiers spécifiques, mais elle a fini par supprimer tous les fichiers du répertoire. Ma commande était find . -name '[^\.txt]' -exec rm {} \;donc ma réticence à utiliser find. Probablement une erreur de ma part mais je ne sais pas ce que j'ai fait de mal. Dans la mesure où ma compréhension se {}réfère à chaque fichier trouvé par la commandefind . -name '[^\.txt]'
PeanutsMonkey
Qu'essayez-vous de faire correspondre avec l'expression régulière?
Rob
10

Vous pouvez utiliser quelques autres outils à partir de la console, comme grep et xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder
0xAF
la source
En quoi est-ce {}différent de celui de -t?
PeanutsMonkey
2
Pas grand chose dans ce cas. La syntaxe alternative pour xargs serait 'xargs cp {} destination_folder'. la syntaxe cp standard prend une ou plusieurs sources et une destination à la fin, lorsque vous utilisez l'option -t, vous pouvez spécifier la destination après -t, puis utiliser le reste de la ligne pour les sources. Je trouve juste l'option -t plus pratique dans ce cas. Dans l'autre exemple, le {} est remplacé par ce qui est canalisé vers xargs (stdin), dans ce cas le nom de fichier.
0xAF
-1

Vous pouvez exécuter la commande suivante facile à utiliser:

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

haa cool !!

Nisan Chhetri
la source