Copy only regular files from one directory to another
cp dir1/* dir2
cp
will not copy directories unless explicitly told to do so (with --recursive
for example, see man cp
).
Note 1: cp
will most likely exit with a non-zero status, but the files will have been copied anyway. This may be an issue when chaining commands based on exit codes:&&
, ||
, if cp -r dir1/* dir2; then ...
, etc. (Thanks to contrebis for their comment on that issue)
Note 2: cp
expects the last parameter to be a single file name or directory. There really should be no wildcard *
after the name of the target directory. dir2\*
will be expanded by the shell just like dir1\*
. Unexpected things will happen:
- If
dir2
is empty and depending on your shell and settings:- you may just get an error message, which is the best case scenario.
dir2/*
will be taken literally (looking for a file/directory named*
), which will probably lead to an error, too, unless*
actually exists.dir2/*
it will just be removed from the command entirely, leavingcp dir1/*
. Which, depending on the expansion ofdir1/*
, may even destroy data:- If
dir1/*
matches only one file or directory, you will get an error fromcp
. - If
dir1/*
matches exactly two files, one will be overwritten by the other (Bad). - If
dir/*
matches multiple files and the last match is a, you will get an error message. - If the last match of
dir/*
is a directory all other matches will be moved into it.
- If
- If
dir2
is not empty, it again depends:- If the last match of
dir2/*
is a directory,dir1/*
and the other matches ofdir2/*
will be moved into. - If the last match of
dir2/*
is a file, you probably will get an error message, unlessdir1/*
matches only one file.
- If the last match of
It's the shell that expands wildcards, not the commands. So cp dir1/* dir2/*
first expands the two wildcards, then calls cp
on the result. This is not at all what you apparently expect: depending on how many files there are already in dir2
, dir2/*
may expand to one or more argument. The command cp
doesn't know which of its arguments came from expanding the first pattern and which ones came from expanding the second pattern. It expects its last argument to be the name of the destination directory. Thus, to copy all the files from the directory dir1
into the directory dir2
, the last argument must be the directory dir2
:
cp dir1/* dir2
Since *
matches all files, cp
attempts to copy all files. This includes directories: directories are files too. It skips directories, but reports an error. It copies the content of special files such as named pipes (something had better be writing to them, or cp
will block), etc.
To copy only regular files, you need to restrict the matching. In zsh, you can use the glob qualifier .
for that:
cp dir1/*(.) dir2
Other shells don't have this. You can use the find
command to filter on file types. Assuming that you're running non-embedded Linux or Cygwin:
find dir1 -maxdepth 1 -type f -exec cp -t dir2 {} +
On Linux, FreeBSD and OSX:
find dir1 -maxdepth 1 -type f | xargs -I {} cp {} dir2