I've been using this bash script:

for i in $(ls); do mv $i a$i; done

to prepend all filenames in a folder with the letter a. I'm afraid that at some point I'll accidentally use this script in the wrong directory and prepend a ton of filenames that I don't want prepended. So I decided to explicitly cite the path to the file. So now my script looks like this:

for i in $(ls /cygdrive/c/Users/path/to/Images); do mv /cygdrive/c/Users/path/to/Images/$i /cygdrive/c/Users/path/to/Images/a$i; done

It does prepend the filename with the letter a, but it also appends the filename with this  symbol.

Any ideas why it would do that?

If it helps any, I'm using cygwin on a Windows 7 box.

Thanks for the help!

  • Is the path always going to be /cygdrive/c/Users/path/to/Images ? If so, is the real prefix you'll be using just the letter 'a'? Is this something you will run multiple times or just a one-off? Judging by your initial statements, you'll run it frequently. – UtahJarhead Oct 2 '12 at 12:06
  • Yes, that will always be the path. And yes, the real prefix will be the letter 'a'. I will be running this multiple times a day, so yes, very frequently. – Devin Oct 2 '12 at 13:00
  • See comments below (in about 5 mins) – UtahJarhead Oct 2 '12 at 13:01

Never parse the output of 'ls'. Do this instead:

for i in *; do mv "$i" "a${i}"; done

The reason is that file names can have characters like \r or \n in them and parsing 'ls' will NOT find them.

Update: Useful information at this link: http://mywiki.wooledge.org/ParsingLs

With the above added information from the OP, use this:

for i in /cygdrive/c/Users/path/to/Images/*; do mv "$i" "${i%/*}/a${i##*/}"; done

THIS WILL DO ONE RELATIVELY BAD THING... it will rename ALL files, every time you run it. This means file 'foo' will be 'afoo'. When you run it again, it will be 'aafoo' then 'aaafoo', etc. You can program around this by avoiding any files that start with 'a' but that will avoid ALL files starting with 'a' even if they have not yet been renamed in the script.

  • I guess I didn't need to store the path in a variable... – UtahJarhead Oct 2 '12 at 13:12
  • I think this will work perfect. I'm making a more or less dumb system in which I copy all the files I need into the Images folder, run the script, and copy them back to whatever folder they originally came from. One question though, I don't fully understand why "${i%/*}/a${i##*/}" is needed instead of just a$i. Thanks again for the help! – Devin Oct 2 '12 at 13:25
  • Understood. Make sure you test it! The logic looks good in my head, but I haven't personally tested it out. For your information, read this link: mywiki.wooledge.org/BashFAQ/073 It describes parameter expansion, which is seen in my script above like this: "${i%/*}" As an example, that particular piece will strip off anything after the very last / which in this case leaves just the path and not the filename. We add the filename after that with "${i##*/}" – UtahJarhead Oct 2 '12 at 13:30
  • Awesome. Thanks again. I will test this out first. – Devin Oct 2 '12 at 13:37

test for correct directory, or move to correct directory (or both):

from here



cd $TargetDirectory
echo "Changing names in $TargetDirectory."

if [ "$PWD" != "$TargetDirectory" ]
then    # Keep from wiping out wrong directory by accident.
  echo "Wrong directory!"
  echo "In $PWD, rather than $TargetDirectory!"
  echo "Bailing out!"
  • Since other users in my office would like to use my script, this is what I would like to eventually have. Thanks for the advice. – Devin Oct 2 '12 at 13:03

Please declare ls /cygdrive/c/Users/path/to/Images as a variable. Please use variable as ${i} instead of $i. also Use, " " for path's .

  • 2
    Could you explain why that would change anything? – slhck Oct 1 '12 at 20:20
  • Please find my updated answer :-) – San Oct 1 '12 at 21:04
  • Your post clarifies things about bash scripting, not in the functionality of the original script. – UtahJarhead Oct 2 '12 at 12:36
  • Your post also recommends parsing the output of 'ls' to a variable which is guaranteed not only to not benefit, but possibly keep the same issues that could be presenting itself already. – UtahJarhead Oct 2 '12 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.