2

On my Mac I am terminal scripting an increment rename of some files in a folder. The files have a number at the end but from a top down approach they are in order:

foobar101.png
foobar107.png
foobar115.png
foobar121.png
foobar127.png
foobar133.png
foobar141.png
foobar145.png
foobar151.png
foobar155.png

When I create and run my loop it works:

DIR="/customlocation/on/mac"
add=1;
for thefile in $(find $DIR -name "*.png" ); do
    cd $DIR
    mv -v "${thefile}" foobar"${add}".png
    ((add++))  
done

However, when it runs the increment it's not as expected:

foobar101.png -> need foobar1.png but is foobar10.png
foobar107.png -> need foobar2.png but is foobar3.png
foobar115.png -> need foobar3.png but is foobar4.png
foobar121.png -> need foobar4.png but is foobar2.png
foobar127.png -> need foobar5.png but is foobar9.png
foobar133.png -> need foobar6.png but is foobar6.png
foobar141.png -> need foobar7.png but is foobar1.png
foobar145.png -> need foobar8.png but is foobar5.png
foobar151.png -> need foobar9.png but is foobar8.png
foobar155.png -> need foobar10.png but is foobar7.png

Ive tried searching on SO, Linux/Unix, Ask Ubuntu, and SuperUser but I don't see any questions that solve the issue of controlling the increment and I dont know if it's something in particular I should be looking at. So how can I control the increment from the lowest number/filename instead of the Mac possibly randomly renaming with an increment so I get the desired output?


EDIT:

After a comment from Etan I was looking into the numerical values at the end and some of the files are named foobarXXXX and that is the issue. The below answer, while awesome and a new approach I will look into still produces the same outcome because of some other files. If I remove all files that are foobarXXXX and only leave files with values of foobarXXX my code and the code in fedorqui's answer work. Is there a way then I can target this while in the loop process or do I have to target all names and test to see the length of values and adjust accordingly?

Community
  • 1
  • 1
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
  • Are those files all in the same directory or do they span sub-directories? If they are in the same directory with no sub-directories then forget `find` here entirely and loop over a glob (which has a guaranteed sort order). – Etan Reisner Jul 16 '15 at 13:32
  • @EtanReisner they have been moved to one directory with no sub-dir – DᴀʀᴛʜVᴀᴅᴇʀ Jul 16 '15 at 14:02
  • Then `for thefile in "$DIR/"*.png; do ...; done` should let you do what you want. Assuming your numbers are naively sortable and not naturally sortable. (The shell will naively sort `1, 10, 11, 12, 2, 3, 4`, etc. which you may want to consider in padding your renamed files to avoid.) – Etan Reisner Jul 16 '15 at 14:08

1 Answers1

3

You cannot rely on the order of a find command, which uses the order that the VFS gives them to it in.

You may, instead, want to sort it:

DIR="/customlocation/on/mac"
add=1;
while IFS= read -r thefile; do
    cd $DIR
    mv -v "${thefile}" foobar"${add}".png
    ((add++))  
done < <(find $DIR -name "*.png" | sort)
#-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Note this uses process substitution, which feed the while loop:

Process substitution is a form of redirection where the input or output of a process (some sequence of commands) appear as a temporary file.

Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • I haven't dived into `IFS` do you know of some solid documentation on it? SO's tag doesn't show a wide selection of items tagged as [tag:ifs]. On my Mac `man ifs` shows nothing. – DᴀʀᴛʜVᴀᴅᴇʀ Jul 16 '15 at 14:05
  • `IFS` is not `if`. See [Word Splitting](http://www.gnu.org/software/bash/manual/bashref.html#Word-Splitting) and [Shell Variables](http://www.gnu.org/software/bash/manual/bashref.html#Shell-Variables). – Etan Reisner Jul 16 '15 at 14:07
  • @Darth_Vader so you want to fetch those names being `foobarXXX` but not with `XXXX`? You may want to use a regex in the `find` command. See for example [Find files with extension with 5 characters or more](http://stackoverflow.com/a/31314180/1983854) and let me know your thoughts. It shouldn't be complicated if the `foobar` part is known to just get those names having XXX. – fedorqui Jul 17 '15 at 08:37