11

I want to copy all files *.pdf to *_0.pdf

How can I do it?

heemayl
  • 91,753
Jonas
  • 111
  • 1
    Don't forget to inspect for collisions. The suggested scripts so far work but, if you run some of them with two files abc.pdf and abc_0.pdf then the renamed abc.pdf may overwrite abc_0.pdf before the latter gets renamed. – Denis de Bernardy Aug 07 '17 at 14:05

5 Answers5

16

A simple way would be to use the mmv command:

mmv '*.pdf' '#1_0.pdf'

You might need to install it first (available in the Universe repository):

sudo apt-get install mmv
heemayl
  • 91,753
sempaiscuba
  • 1,433
  • 4
    To save you an apt-cache show mmv: mmv is a program to move/copy/append/link multiple files according to a set of wildcard patterns. This multiple action is performed safely, i.e. without any unexpected deletion of files due to collisions of target names with existing filenames or with other target names. – user1717828 Aug 07 '17 at 14:58
10

With rename (prename):

rename -n 's/\.pdf$/_0$&/' *.pdf
  • \.pdf$ matches .pdf at the end of the filename
  • in the replacement, the match is prepended by _0: _0$&
  • drop -n for actual action

With bash parameter expansion:

for f in *.pdf; do pre="${f%.pdf}"; echo mv -- "$f" "${pre}_0.pdf"; done
  • pre="${f%.pdf}" saves the portion of the filename before .pdf as variable pre

  • while mv-ing _0.pdf is appended to $pre: ${pre}_0.pdf

  • drop echo for actual action


Example:

% rename -n 's/\.pdf$/_0$&/' *.pdf
rename(egg.pdf, egg_0.pdf)
rename(spam.pdf, spam_0.pdf)

% for f in *.pdf; do pre="${f%.pdf}"; echo mv -- "$f" "${pre}_0.pdf"; done
mv -- egg.pdf egg_0.pdf
mv -- spam.pdf spam_0.pdf
wjandrea
  • 14,236
  • 4
  • 48
  • 98
heemayl
  • 91,753
  • with rename.ul it is even more simple ;) – Rinzwind Aug 07 '17 at 13:07
  • @Rinzwind rename.ul which comes with util-linux, does not give enough flexibility to me while the prename (perl script) let me do all the perl capabilities. So prename is my way to deal with these stuffs. – heemayl Aug 07 '17 at 13:12
  • echo abc > abc.pdf; echo abc_0 > abc_0.pdf; for f in *.pdf; do pre="${f%.pdf}"; echo mv -- "$f" "${pre}_0.pdf"; done (The rename version will skip instead of overwriting.) – Denis de Bernardy Aug 07 '17 at 14:11
3

Do you want to rename or copy?

To rename, you can use emacs:

  1. Open the parent directory as a dired buffer
  2. Type M-x wdired-change-to-wdired-mode
  3. Use M-x query-replace to replace '.pdf' with '_0.pdf'
  4. Type C-x C-s to save the buffer
2

Do you want to rename or copy the files? For both, you can simply use a for loop and mv (move, also renames) or cp (copy):

for i in *.pdf; do mv "$i" "${i/%.pdf/_0.pdf}"; done

or rather

for i in *.pdf; do cp "$i" "${i/%.pdf/_0.pdf}"; done

The quotation marks are only needed if (one of) your files contains spaces.

Quick explanation: ${i/%.pdf/_0.pdf} takes variable i and substitutes “.pdf” by “_0.pdf” if it is found at the end of the string (hence %). Read more about bash's amazing superpowers here.

dessert
  • 39,982
  • Considering what Denis de Bernardy wrote in his comment to the question: This solution will overwrite a file abc_0.pdf with the content of abc.pdf, but only after moving/copying abc_0.pdf to abc_0_0.pdf first, because abc_0.pdf comes before abc.pdf for the bash (with my localisation). When in doubt, just check the file order first with for i in *.pdf; do echo $i; done. – dessert Aug 09 '17 at 11:30
-1

Simple solution files on same directory

On sh shell, rename will help you:

rename .pdf _0.pdf *.pdf

Execute the comand on directory with the pdf files.

Files inside directory recursive

If you have the files inside directories and want to find all of then and replace:

find . -iname "*.pdf" | fgrep -v _0.pdf | xargs -n1 echo rename .pdf _0.pdf

Psycho
  • 1