linux - changing order of files

06
2014-04
  • To Do

    I have a series of files named in alphabetical order (xaa.tif to xdg.tif). I need to reverse the order of the filenames so that the last file is processed first in a script. I would like to rename them by adding a number at the beginning of the filename (01xdg.tif to 60xaa.tif).

    How can I do that with a bash script on Linux?

  • Answers
  • Michael Kjörling

    Because the file names contain no special characters, including spaces, this can be pretty easily accomplished using ls -r (that's -r for --reverse, not -R for --recursive).

    /tmp/todo$ ls
    /tmp/todo$ touch ab bc bd ef
    /tmp/todo$ ls
    ab  bc  bd  ef
    /tmp/todo$ ls -r
    ef  bd  bc  ab
    /tmp/todo$
    

    Then you can rename the files using something like:

    num=1
    for file in $(ls -r)
    do
        mv $file "$(seq --format='%02g' $num $num)${file}"
        num=$(( $num + 1 ))
    done
    

    This uses seq to format the number to use two digits (2) zero-padded from the left (%0) with no decimal places (g) for a total format string of %02g. There's probably a more efficient way to do it, but with so few files, I wouldn't bother micro-optimizing.

    This simply iterates over the list of files (in reverse order), renames each one in turn and increments a counter for each rename.

    The final result is:

    /tmp/todo$ ls
    01ef  02bd  03bc  04ab
    /tmp/todo$
    

    Note that the above may very well fall apart if the file names have anything more unusual in them than simple a-z, periods and digits to begin with. Particularly, I'm not sure how well it'll handle spaces.

  • Michael Kjörling

    You can user sort command in Linux

    lets say the directory contains following files

    # ll /tmp/sort_folder
    total 0
    -rw-r--r-- 1 root root 0 Dec 18 19:51 a
    -rw-r--r-- 1 root root 0 Dec 18 19:51 b
    -rw-r--r-- 1 root root 0 Dec 18 19:51 v
    

    The sort command will give you output as below(by default ascending)

    # ll /tmp/sort_folder | sort
    -rw-r--r-- 1 root root 0 Dec 18 19:51 a
    -rw-r--r-- 1 root root 0 Dec 18 19:51 b
    -rw-r--r-- 1 root root 0 Dec 18 19:51 v
    

    To reverse sort(descending) you can we -r(reverse) option for sort command

    # ll /tmp/sort_folder | sort -r
    total 0
    -rw-r--r-- 1 root root 0 Dec 18 19:51 v
    -rw-r--r-- 1 root root 0 Dec 18 19:51 b
    -rw-r--r-- 1 root root 0 Dec 18 19:51 a
    
  • Philip Kearns

    This should work:

    #!/bin/bash
    #
    Count=0
    ls -r | while read FileName
    do
        FmtCount=`printf %02d $Count`
        mv -i $FileName $FmtCount$FileName
        Count=$((Count+1))
    done
    

    Here's the explanation:

    • ls -r lists the files in reverse order
    • printf formats the count into two zero-padded digits
    • The backquotes turn the output into a string

    I think the rest is self-explanatory, but if not please ask


  • Related Question

    linux - Replace files with others from other folder matched by first token in filename
  • Alasdair

    Lets say I have two folders:

    ls /A/
        01 - IncorrectName.flac
        02 - otherincorrect.flac
    
    ls /B/
        01 - CorectName.flac
        02 - Othercorrect.flac
    

    How would I move the files from dir A to B, but using the filenames from dir B?

    Could I be doing this automatically with $ mv /A/01 - IncorrectName.flac /B/01 - CorrectName.flac ?

    The first 5 characters of all filenames are always "NN - "


  • Related Answers
  • choroba

    I am not sure I understand what you want, but this could be it in bash:

    #! /bin/bash
    for file in "$1"/[0-9][0-9]*.flac ; do
        newname="$2"${file#"$1"}
        newname=${newname:0:5+${#2}}
        mv "$file" "$newname"*
    done
    

    Update: should work with command line arguments. The trick was the length of the string was not constant anymore, hence ${#2}.