2

I have to make a script on Ubuntu, which will rename all of files in specified by path directory to be uppercase. I've already found a loop which will rename files, but I'm not sure how I can pass a path to this loop. Can you help me?

Here's the loop:

for f in *; do 
    mv "$f" "$f.tmp"; 
    mv "$f.tmp" "`echo $f | tr "[:lower:]" "[:upper:]"`"; 
done

I've tried to pass the path like

for f in path_to_dir* ...

but what it does, it's just somehow making a directory .tmp

terdon
  • 242,166
gtgt
  • 23

2 Answers2

4

I'd do something like:

#! /bin/zsh -
ret=0
autoload zmv
for dir do
  (cd -P -- "$dir" && zmv '*(#qN)' '$f:u') || ret=$?
done
exit "$ret"

With that script being called as:

that-script /path/to/dir /path/to/other/dir...
3

I suspect you did something like for f in /path/to/dir* instead of /path/to/dir/*. The former will look for files and directories in /path/to whose name starts with dir while the latter will iterate over the contents of the direrctory.

In any case, that wouldn't help you because the tr command you are using would change everything, including /path/to/dir to upper case, leaving you with /PATH/TO/DIR which doesn't exist. The good news is that you can do it in a much simpler way.

If you're using bash, you can use ${var^^} to make a variable's contents upper case. So you can just do:

for f in /path/to/dir/*; do
    ## get the file's name
    name=$(basename -- "$f")
    ## make the new name
    mv -- "$f" /path/to/dir/"${name^^}"
done

Or, to avoid typing out the directory name twice, you could save it in a variable:

targetPath="/path/to/dir"
for f in "$targetPath"/*; do
    ## get the file's name
    name=$(basename -- "$f")
    ## make the new name
    mv -- "$f" "$targetPath"/"${name^^}"
done    

However, this is one of the cases where it is simpler and cleaner to just cd into the target directory and work there:

targetPath="/path/to/dir"
cd -- "$targetPath" && 
for f in *; do
    mv -- "$f" "${f^^}"
done

Or, to avoid ending up in the new directory, run the loop in a subshell:

targetPath="/path/to/dir"
( cd -- "$targetPath" && 
for f in *; do
    mv -- "$f" "${f^^}"
done
)

Finally, you can also do all this using perl-rename (known as rename on Ubuntu and installable with sudo apt install rename):

rename -n 's|([^/]+)$|uc($1)|e' /path/to/dir/*

The -n makes rename just print out what it would do without doing it. If you're satisfied it works, run it again without the -n to actually rename the files.

terdon
  • 242,166