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?

4 Answers 4



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 !.

  • 2
    find . -name [^\.php] -exec cp {} /path/to/location \; be careful for files with special characters.
    – Rob
    Jun 25, 2012 at 18:24
  • @Darth Android - Thanks. I wasn't aware that cp and other binaries were not able to expand regular expressions. Would you mind elaborating what each of the options and arguments mean in the sample example you gave? I know that . refers to the the current directory but what do !, {}, \;, etc refer to as well what they mean? For example why do you have to escape the ;? Jun 25, 2012 at 20:30
  • @Rob - What do you mean by special files? Jun 25, 2012 at 20:30
  • @Rob - I attempted a similar expression to remove specific files however it ended up deleting all files in the directory. My command was find . -name '[^\.txt]' -exec rm {} \; hence my reluctance to use find. Probably a mistake on my part but am unsure what I did wrong. As far as my understanding {} refers to each file found by the command find . -name '[^\.txt]' Jun 25, 2012 at 20:33
  • What are you trying to match with the regex?
    – Rob
    Jun 26, 2012 at 3:42

You may use few other tools from console, like grep and xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder
  • How is {} different to that of -t? Jun 25, 2012 at 20:34
  • 2
    Not much in this case. Alternate syntax for xargs would be 'xargs cp {} destination_folder'. standard cp syntax takes one or many sources and one destination in the end, when you use -t option, you can specify the destination after the -t, then use the rest of the line for sources. I just find the -t option more convenient in this case. In the other example the {} is replaced by what is piped to xargs (stdin), in this case the filename.
    – 0xAF
    Jun 25, 2012 at 20:45
  • This approach assumes certain limitations on the filenames used, e.g. no newlines. May 16, 2022 at 10:49

To copy 100 log files into another log2 folder of same directory, I use following

cp app.log.[0-9][0-9] log2


You can run following command easy to use:

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

cool haa!!

  • Does not use regular expressions. May 16, 2022 at 10:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .