1

I have doubt. I have to rename the file with sequence number 1 to 10. i am able to create a file with following parameter.

touch file.$(date +%Y).$$.{1..10}

But i can't rename the file using the following command. Why {1..10} is not taking.Because i want rename a file as. mv command will take {1..10} ?

file.201704.<PID>.1
file.201704.<PID>.2
.
.
.
.

so below command is right?

for file in $(ls);
do

mv $file file.$(date +%Y%m).$$.{1..10}
done
  • The touch command creates ten different files because that's what the brace expansion generates. I can't imagine that you want to create ten copies with a single mv so it is completely unclear what you are actually trying to accomplish here. Could you please [edit] your question to explain your goal? Including a precise error description would also be good form ("it doesn't work" how exactly?) – tripleee Apr 22 '17 at 08:24
  • Tangentially, see also https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells – tripleee Apr 22 '17 at 08:28
  • I'll leave open, this seems a common mistake about {1..10} and shell expansion as well. – Archemar Apr 22 '17 at 13:39

1 Answers1

3

The brace expansion {1..10} will cause the command line to be expanded to include several arguments.

For example, the touch command line will be expanded to something like

touch file.2017.5878.1 file.2017.5878.2 file.2017.5878.3 file.2017.5878.4 file.2017.5878.5 file.2017.5878.6 file.2017.5878.7 file.2017.5878.8 file.2017.5878.9 file.2017.5878.10

before being executed. This is ok since the touch utility takes any number of arguments on the command line. Note: this creates 10 files, not one file.

However, the mv utility have different semantics compared to touch. It expects one or several source files/directories and one single target file/directory at the end.

This means that when

mv $file $file.$(date +%Y%m).$$.{1..10}

is expanded to something like

mv file file.2017.5878.1 file.2017.5878.2 file.2017.5878.3 file.2017.5878.4 file.2017.5878.5 file.2017.5878.6 file.2017.5878.7 file.2017.5878.8 file.2017.5878.9 file.2017.5878.10

it's assumed that you want to move all the files, except for the last thing on the command line. It furthermore expects the last thing on the command line to be a directory name (since you're moving multiple things).

It is unclear to me what you actually want to do in that loop, so I can't further comment on how to go about resolving this issue.

When it comes to the loop itself, please don't ever use the output of ls like that. Instead, do

for file in ./*; do
    # process "$file"
done

The output of ls is for you to look at, it's not fit for consumption by a script for several reasons. See http://unix.stackexchange.com/questions/128985/why-not-parse-ls

Also, always double-quote your variables. See http://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells

Kusalananda
  • 333,661