Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

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

share|improve this answer
2  
find . -name [^\.php] -exec cp {} /path/to/location \; be careful for files with special characters. –  Rob Jun 25 '12 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 ;? –  PeanutsMonkey Jun 25 '12 at 20:30
    
@Rob - What do you mean by special files? –  PeanutsMonkey Jun 25 '12 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]' –  PeanutsMonkey Jun 25 '12 at 20:33
    
What are you trying to match with the regex? –  Rob Jun 26 '12 at 3:42
show 1 more comment

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
share|improve this answer
    
How is {} different to that of -t? –  PeanutsMonkey Jun 25 '12 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 '12 at 20:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.