Linux – How to physically reorder files `03.mp3 01.mp3 02.mp3` (`ls -f`) in a directory

findlinuxls

The physical order of the files matters when I copy them onto my USB stick and listen in car mp3 player. Most of my music album folders are unsorted, e.g. ls -f may produce:
03.song3.mp3
01.song1.mp3
02.song2.mp3

When I copy that folder onto my USB stick, the files get copied in that order. My car mp3 player displays the files in the unsorted order, which is not what I want.
I can subsequently reorder the files on the USB stick (see: How to reorder folders? (as displayed in `ls -U`)), but could avoid that altogether if I could reorder them within that directory them on my hard drive (ext4)? Is there a way of doing that?

(Failing that, there might be a way of writing a find command, that gets the files, sorts them, and then copies them in order??) Any suggestions?

Best Answer

It's unlikely that you'll be able to do this on ext4. Unlike FAT(32), which used a linear table of files in a directory, modern filesystems use complex structures such as B+tree (NTFS, XFS) or hashed B-tree (ext3/4), where all entries are sorted according to a specific algorithm.

In particular, ext3/4 sorts files according to the hash value of their name, so you always get the same files in the same order. It's possible to disable the dir_index feature via tune2fs, but it might cost you performance if you have directories containing many files.


A very basic command for this could be cp dir/* otherdir/, where the shell sorts names when expanding arguments, and cp simply copies them in the order given.

Something more complex, for copying subdirectories:

#!/usr/bin/env bash
srcdir=$1
destdir=$2

find "$srcdir" \( -type d -printf "0dir %P\0" \) \
            -o \( -type f -printf "1file %P\0" \) |
sort -z | while read -r -d '' type path; do
    case $type in
        "0dir") mkdir -vp "$destdir/$path";;
        "1file") cp -v "$srcdir/$path" "$destdir/$path";;
    esac
done
Related Question