When using the cp command to copy multiple files, can you rename the files when you copy it?

72,158

Solution 1

cp can copy a single file to a different filename (i.e. "rename" the destination), but there is no way to specify different filenames for multiple files. So the answer is no, cp can not rename when copying multiple files.

When cp is given more than two arguments, all of the files are copied to the final argument (a directory). e.g. cp file1 file2 file3 /path/to/destdir/

With GNU cp there is a -t or --target-directory option which allows you to specify the destination before the source files. e.g. cp -t /path/to/destdir/ file1 file2 file3

-t is partcicularly useful when used with, e.g., ... | xargs cp -t destdir/ or find ... -exec cp -t destdir/ {} +.

Some other GNU tools, including mv and ln also have the same -t aka --target-directory option.


If you want to rename multiple files when you copy them, the easiest way is to write a script to do it.

You can generate a large part of the script automatically. There are many methods of doing this, here's one of the easiest (using filenames matching *.txt as the example):

find . -maxdepth 1 -name '*.txt' \
   -exec echo cp \'{}\' \'/path/to/dest/newfile\' \; > mycp.sh

(i've split the file command onto two lines here to avoid a horizontal scrollbar but this can be typed all on one line)

This will produce output like this:

$ ls -1 *.txt
dict.txt
qstat.txt
x.txt
foo'bar.txt

$ find . . -maxdepth 1 -name '*.txt' \
  -exec echo cp \'{}\' \'/path/to/dest/newfile\' \;
cp './qstat.txt' '/path/to/dest/newfile'
cp './x.txt' '/path/to/dest/newfile'
cp './dict.txt' '/path/to/dest/newfile'
cp './foo'bar.txt' '/path/to/dest/newfile'

Then edit mycp.sh with your preferred text editor and change newfile on each cp command line to whatever you want to rename that copied file to. If you don't want to rename some of the file(s), just delete newfile from the destination, leaving only the path as the destination.

Note the final line of the output, with './foo'bar.txt' as the source filename - because the filename contains a ' character, this line needs some extra editing to change the embedded ' to '\'', so that the line looks like this:

cp './foo'\''bar.txt' '/path/to/dest/newfile'

Alternatively, if you have GNU sed (with the -z or --null-data option for NUL-separated lines) and xargs you could do that automatically with :

find . -maxdepth 1 -name '*.txt' -print0 | 
    sed -z -e "s/'/'\\\''/g" | 
    xargs -0 -r -i echo cp \'{}\' \'/path/to/dest/newfile\' > mycp.sh

Once you've finished editing the script, you can run it with sh mycp.sh.

Solution 2

No, cp does not rename the files that it copy. It copies each file to a file with the same base name in the target directory. The only case where cp changes the file name is when copying a single file and specifying a full name rather than a directory as the target.

Some versions of cp can rename the already-existing target file if there is one.

If you want to rename files as they're being copied, you can use pax. This is a utility to copy a directory tree or create or unpack an archive. It is a mandatory utility on POSIX systems, but some Linux distributions don't install it by default (it's available as a package though). With pax, you can rename files by applying sed-style s/REGEX/REPLACEMENT/ instructions.

pax -rw -pe -s/2015/2016/ source/ target/

copies files like source/foo-2014.txt and source/2015.txt to target/foo-2014.txt and target/foo-2016.txt respectively.

Share:
72,158

Related videos on Youtube

Ice
Author by

Ice

Updated on September 18, 2022

Comments

  • Ice
    Ice almost 2 years

    I was wondering if this is true or false.

    • phk
      phk over 8 years
      Please be more specific in what way you would plan on renaming it, following a pattern or an explicit mapping?
  • phk
    phk over 8 years
    The method to generate a script breaks with files that have an ' in their name.
  • Alessio
    Alessio over 8 years
    1. it doesn't break, it just produces a line that needs more editing (to add a backslash before any embedded '). 2. embedded ' characters in filenames are far less common than embedded spaces. 3. it's not meant to be perfect, it's meant to be a simple example. 4. if someone creates files with embedded 's or other problematic characters, it's up to them to be aware of and deal with the consequences.
  • phk
    phk over 8 years
    I totally agree that a perfect solution is rarely needed and in fact a simpler and more elegant solution which deals with the majority of real-life cases is often preferable but I also think that pointing out in which way a solution is limited is important because it alerts people about the problems with file names that can arise when file names can have any character but \0 and /. Hopefully this way people are more prepared for cases where one has to be especially careful to handle any file name well, e.g. in order to not introduce any security holes.
  • rslemos
    rslemos over 6 years
    UNBELIEVABLE. Being a heavy linux user for more than 17 years now and never, NEVER heard of the pax utility. Did the job very nicely (I had to copy a deep and wide hierarchy with ":" [colons] to an exFAT filesystem). Unfortunately I could only give +1.