Linux – How to use regular expressions with the cp command in Linux

cplinux

I am attempting to only copy a subset of files from one directory to another using cp however am greeted with the message cp: cannot stat [^\.php]': No such file or directory. Is there a way to use regular expressions only using the cp command?

Best Answer

No.

The cp command does not possess the capability to process any of its arguments as regular expressions. Even wildcards are not handled by it (or most executables); rather they are handled by the shell.

cp test/* test2/ is actually expanded by bash, and all that cp really sees for its arguments are cp test/file1 test/file2 test/file3 test2/ (or whatever is appropriate based upon the actual contents of test/).

Also, I don't think your expression, [^\.php], will match what you want it to (it doesn't match only files that contain .php).

You probably want to look into the find utility to filter out a list of files based upon regular expression, and then use xargs to apply the returned file list to the cp command (presuming find doesn't have a built-in handler for copying files; I'm not intimately familiar with the tool).

You might try:

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

This says to search the current directory recursively for files which do not contain ".php" in the path and copy them into /destination/folder/.

As requested, a more specifc breakdown of the arguments:

  • . - Location to start the search - in this case, the current directory
  • ! - "Not" operator, invert the result of the next test
  • -iregex - Case-insensitive regular expression test. Next argument is the expression.
  • ".*\.php.*" - Regular expression matching <Anything>.php<Anything> - Any file that has ".php" somewhere in the path. (Note, including being inside a folder which contains ".php" in the name, you'd need a more complex expression to match only the files)
  • -exec - Execute a command if the preceding tests return true. Next argument is the command, all remaining arguments up to ; are passed to the command. the {} is a special argument representing the filename.
  • cp - The command that find` should run on each of the matched path names.
  • {} - The path to the file that was found, passed to cp as an argument so that it knows what file to copy
  • /destination/folder/ - argument passed to cp, telling cp where it should copy the file to.
  • \; - This is the ; terminator that -exec is looking for. We escape it with a \ so that your shell doesn't try to parse it and instead feeds it as an argument to the command (find)

It's rather difficult to write a regular expression which matches "strings that do not have .php", so we instead tell find to search for strings that do contain .php and then invert the results with !.

Related Question