-2
cd /home/foo/

for f in `seq -w 01 10`
   do
   cat $f > /home/foo/cloned_files/"$f".$i
done

situation: i have only 1 file in /home/foo. i want to clone that file 10 times and add the iteration number to the filename. in the end, i should have 10 files identical in content but with a suffix indicating its sequence number.

example: /home/foo/xfile.txt

after executing the script, i should have: xfile.txt.01, xfile.txt.02, xfile.txt.03...xfile.txt.10 in /home/foo/cloned_files/

any help would be much appreciated. thank you

user2585000
  • 113
  • 1
  • 9
  • 3
    Why are you doing `cat` and a redirect instead of just using `cp`? – Stephen Newell Mar 20 '18 at 21:43
  • 1
    `seq` is not POSIX-specified, not part of bash, and otherwise not portable / guaranteed to have any particular behavior on any given system, even when that system is known to run bash. Much safer to do something like `for ((f=1; f<=10; f++)); do printf -v num '%02d' "$f"; echo "Number is $num"; done` – Charles Duffy Mar 20 '18 at 22:05
  • 1
    Anyhow, it looks like you want to iterate over files, so you should have two loops, one to loop over your files, one to loop over your numbers: `for filename in *; do [[ -f "$filename" ]] || continue; for (( i=1; i<=10; i++)); do printf -v num '%02d' "$num"; cp "$filename" cloned_files/"$filename.$num"; done; done` – Charles Duffy Mar 20 '18 at 22:09

2 Answers2

4

Try this, the canonical way using your tag: in pure :

for i in {01..10}; do
    cp "filename" "/path/to/xfile.txt.$i"
done

if you need the integer range to be dynamic :

integer=10 # <= variable
for i in $(seq -w 1 $integer); do
    cp "filename" "/path/to/xfile.txt.$i"
done

And like @Charles Duffy said in comments, a more portable solution (seq is not bash related, it's an external command) :

for ((i=1; i<=10; i++)); do
    printf -v num '%02d' "$i"
    cp "filename" "/path/to/xfile.txt.$num"
done

To go further : TestsAndConditionals

man cp :

CP(1)

NAME

cp - copy files and directories

Notes :

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
  • thank you, the output file is only one file --> xfile.txt.{01..10} – user2585000 Mar 20 '18 at 22:02
  • 1
    @user2585000, does your real code perhaps get `10` from a variable, instead of hardcoding it? That doesn't work, as described in [BashPitfalls #33](http://mywiki.wooledge.org/BashPitfalls#for_i_in_.7B1...24n.7D). Otherwise, the worst behavior I'd expect with constants would be starting with `1` instead of `01` if it's bash 3.x in use. – Charles Duffy Mar 20 '18 at 22:07
  • 1
    You tagged the POST bash, so use bash :) Added another snippet for dynamic range – Gilles Quénot Mar 20 '18 at 22:36
  • 1
    Added @CharlesDuffy recommendations – Gilles Quénot Mar 20 '18 at 23:57
  • 1
    I'd be careful about using "portable" to describe my suggestion -- it's portable to platforms that don't provide the OP's specific `seq` implementation; it's *not* portable to non-bash shells. (For ksh, f/e, one would want to make it `num=$(printf '%02d' "$i")`; for POSIX sh, the C-style `for` loop needs to be replaced, as with `i=1; while [ "$i" -le 10 ]; do ...; i=$((i + 1)); done` – Charles Duffy Mar 21 '18 at 00:21
2

Another option using GNU Parallel

parallel --dry-run cp file /elsewhere/file.{} ::: {01..10}

Sample Output

cp file /elsewhere/file.07
cp file /elsewhere/file.08
cp file /elsewhere/file.09
cp file /elsewhere/file.06
cp file /elsewhere/file.05
cp file /elsewhere/file.04
cp file /elsewhere/file.03
cp file /elsewhere/file.02
cp file /elsewhere/file.01
cp file /elsewhere/file.10

Remove --dry-run and run the command again to actually do it if the output looks good.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432