How can I copy a file in a bash script and rename it while copying and place it in the same directory

31,344

Solution 1

No need for bash here, any standard sh interpreter implementation will do:

#! /bin/sh -
ret=0
for file do
  dir=$(dirname -- "$file")
  case $dir in
    (*[!/]*) dir=$dir/ # handle / and // specially
  esac
  base=$(basename -- "$file")
  name=${base%.*}
  name=${name:-$base} # don't consider .bashrc the extension in /foo/.bashrc
  ext=${base#"$name"}
  new_file=$dir${name}_copy$ext
  cp -- "$file" "$new_file" || ret=$?
done
exit "$ret"

(assumes the file and dir names don't end in newline characters).

(of course, that will also work with bash since bash is one of those standard sh interpreters.)

For a bash-specific solution, you could try:

#! /bin/bash -
ret=0
re='^((.*/)?[^/])(([^/]*)(\.))?([^/]*)/*$'
for file do
  if [[ $file =~ $re ]]; then
    if [[ ${BASH_REMATCH[5]} ]]; then
      suffix=_copy.${BASH_REMATCH[6]}
    else
      suffix=${BASH_REMATCH[6]}_copy
    fi
    cp -- "$file" "${BASH_REMATCH[1]}${BASH_REMATCH[4]}$suffix" || ret=$?
  else
    printf >&2 '%s\n' "$0: Error: refusing to copy $file"
    ret=1
 fi
done
exit "$ret"

Solution 2

Since the OP is asking for a bash solution. Here is one that does.

#!/bin/bash

if [[ ! -f $1 && $(($# != 1)) ]]; then 
    printf '%s\n' "Provide a filename"
    exit 1
fi

inFile="$1"
fileExt="${1#*.}"
destFile="${1%.*}"

cp -- "$inFile" "${destFile}_copy.$fileExt"  # As suggested, so the files that start with a dash are not ignored.

Solution 3

#!/bin/bash
ss=0
for file do
    cp -fp -- "$file" "${file%.*}_copy.${file##*.}" || ss=$?
done
exit $ss

This fails if file does not have a dot extension part. If you need that to work use Stéphane Chazelas's solution.

Share:
31,344

Related videos on Youtube

Gilles 'SO- stop being evil'
Author by

Gilles 'SO- stop being evil'

Updated on September 18, 2022

Comments

  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 2 years

    How would I copy a file "file.doc" and rename it while copying to "file_copy.doc" and place it in the same directory ?

    And this only by calling the script and adding the file name in the argument:

    bash launch_copyer file.doc
    
    • Admin
      Admin about 9 years
      If you don't insist on Bash, I think there are ready-made tools for that as well.
    • Admin
      Admin over 2 years
      Rename the file to what? Copy the file to where?? What if there is already a file named file_copy.doc??
  • Marek Zakrzewski
    Marek Zakrzewski about 9 years
    That's not what OP asked either. What it does is just copy source file to dest file. There is a shorter step though. cp /path/to/dir/{file.doc,file_copy.doc} Again, the OP wan'ts to use the positional parameter $1
  • Stéphane Chazelas
    Stéphane Chazelas about 9 years
    That will fail in a number of cases like with those arguments: -foo-, foo.tar.gz, /foo/bar, foo.d/bar.doc. I'm not sure why you insist on the argument being a regular file or symlink to regular file, that's not part of the requirement. Error messages should be displayed on stderr.
  • roaima
    roaima about 9 years
    Like mine, this also seems to fail if the file has no dotted extension
  • Stéphane Chazelas
    Stéphane Chazelas about 9 years
    @roaima, well, it meant to address that, but there was a typo. Should work now. It also addresses things like foo.d/bar, foo/.bashrc, /foo properly which also solution don't...
  • Stéphane Chazelas
    Stéphane Chazelas about 9 years
    @val0x00ff, more like cp /path/to/dir/file{,_copy}.doc here.
  • Marek Zakrzewski
    Marek Zakrzewski about 9 years
    @StéphaneChazelas that is even shorter indeed. Good to know.
  • holasz
    holasz about 9 years
    This won't copy files starting with a dash like -foo as mentioned.
  • roaima
    roaima about 9 years
    @holasz fixed that. Not planning to fix dot-extension files.