LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Actual file order in a directory (https://www.linuxquestions.org/questions/linux-software-2/actual-file-order-in-a-directory-915506/)

Calgarian 11-25-2011 10:08 AM

Actual file order in a directory
 
I have a TV that will do a slide show of photos from a USB device. I have a directory of my recent vacation photos with a sub-directory for each location we visited. The photos are properly in order by file name in Dolphin, Digikam and Gwenview. When I copy this directory structure to a USB device and show it on the TV the photos are not in order by file name. I have done research and found that this is a common problem in many devices like TVs and mp3 players. The displayed order and the physical file order in a directory in Linux are not the same. I did find a script called findalpha that stated it would correct this issue by creating a temporary directory and copying files one-by-one, in file name order, and then back to the original directory so that the actual order and file name order match. It doesn't work on my Kubuntu 11.10. The jpg files are still not in file name order on the USB device. I can't seem to locate any other solution. Has anyone else solved this problem?

jschiwal 11-25-2011 10:28 AM

You may need the file names to start with a number. For example, my DVD player expects that for pictures and mp3 files; such as
01_dog.jpg
02_cat.jpg

The order given in a graphical file manager doesn't indicate any order in a directory. You can change how files are sorted, name, date, etc. Either by clicking on the column header, or by an option in the menu.

If the order the TV sees reflects the order they were copied, you could copy the files to the USB pendrive in the shell. The wild card, e.g. cp *.jpg /media/usbdrive/, will result in the jpeg files being sorted and copied in that order.

Calgarian 11-25-2011 11:02 AM

The idea of starting with a number did not work for me. However, the use of cp *.jpg /media/'stick name', appears to have worked. Now I need to develop a bash script that will do this recursively down the directory structure. Thanks for the tip.

jefro 11-25-2011 04:44 PM

I think the order is ls -f

David the H. 11-27-2011 08:07 AM

Check out fatsort. It's probably already in your distro's repositories.

http://fatsort.sourceforge.net/

Also, if you would post the script you have, and whatever error messages/output you get, we may be able to figure out why it isn't working.

Finally, note that names are generally sorted in ascii string order (or the order of the locale your system is set to), rather than numerically. So 10 will usually come before 2. If this is a problem you may want to zero-pad the numbers first.

I've written a script that will automatically pad the numbers in filenames:

Code:


#!/bin/bash

# Pads numbers in file names if found.
# See help message for more.

# Set the environment
shopt -s extglob
IFS=""

BCYAN="${BCYAN:-\e[1;36m}"    #Define some color codes, for prettified output.
#BGREEN="${BGREEN:-\e[1;32m}"  #Uses environment defaults if they exist.
#BRED="${BRED:-\e[1;31m}"
#BBLUE="${BBLUE:-\e[1;34m}"
#BMAGENTA="${BMAGENTA:-\e[1;35m}"
RESET="${RESET:-\e[0m}"

#set the default padding level
pad=2

# Set up the help dialog:
help+=( '' )
help+=( '\tA quick script to zero-pad files that contain numbers.' )
help+=( '\tIt will only pad the first number string it finds in the name, and ignores files without numbers in their names.' )
help+=( '' )
help+=( "\tUsage: \t${BCYAN}${0##*/} [-n <num>] <files>${RESET}" )
help+=( "\t\t${BCYAN}${0##*/} -h${RESET}" )
help+=( '' )
help+=( '\tUse -n to specify the number of digits to pad, from 1-9.  Defaults to '"$pad"' if not used.' )
help+=( '\tIf no files are given, it processes the current directory.' )
help+=( '' )


# Process input options
# If "-h" print help & exit.
# If "-n" test for valid inputs and set "pad" variable
# Ignore anything else
while getopts ":hn:" opt; do

        case "$opt" in

                h)        IFS=$'\n'
                echo -e "${help[*]}" >&2
                exit "2"
                ;;

                n)        if [[ "$OPTARG" =~ [^[:digit:]] ]] || (( "10#$OPTARG" < 1 )) || (( "10#$OPTARG" > 9 )); then
                                echo
                                echo -e "${BCYAN}invalid option: [$OPTARG].${RESET}" >&2
                                echo -e "${BCYAN}-n must be an integer from 1 to 9${RESET}" >&2
                                echo -e "${BCYAN}Falling back to the default of $pad${RESET}"
                                echo
                        else
                                pad="$(( 10#$OPTARG ))"
                        fi
                ;;

                \?) echo -e "${BCYAN}Invalid option: [-$OPTARG].  Ignoring.${RESET}" >&2
                ;;
        esac
done

shift $(( OPTIND - 1 )) ; OPTIND=1

# Now test for input files.
# If nothing given, set input parameters to files in current directory.
if [[ -z "$*" ]]; then
        set -- ./*
fi

# Process files in input parameters
for file in "$@" ; do

        # Ignore files without digits
        [[ "$file" != *[0-9]* ]] && continue

        # Split filename into prefix-digits-suffix
        [[ "$file" =~ ([^[0-9]*)([0-9]+)(.*) ]]

        # Pad digits to desired width
        printf -v numpad "%0*d" "$pad" "${BASH_REMATCH[2]##*(0)}"

        # Add old and new filenames to arrays for final processing
        oldfile+=( "$file" )
        newfile+=( "${BASH_REMATCH[1]}${numpad}${BASH_REMATCH[3]}" )

done

# If there are any files to rename, ask to confirm the operation.
# And rename if confirmed.
if [[ -n "${oldfile[*]}" ]]; then

        echo
        echo -e "${BCYAN}Rename the following files?${RESET}"       
        echo
        for i in "${!oldfile[@]}" ; do
                echo -e "${oldfile[i]/#$PWD/.}\t-->\t${newfile[i]/#$PWD/.}"
        done
        echo
        read -p "(y/n): "
        echo

        case "$REPLY" in

                y|Y*)          for i in "${!oldfile[@]}" ; do
                                        mv -n "${oldfile[i]}" "${newfile[i]}"
                                done
                                echo
                ;;

                *)                echo -e "${BCYAN}Aborting.${RESET}"
                                echo
                                exit 1
                ;;
        esac

# Otherwise just exit.
else
        echo
        echo -e "${BCYAN}No files to rename.${RESET}" >&2
        echo -e "${BCYAN}Exiting.${RESET}" >&2
        echo
        exit 1
fi

exit 0


Calgarian 11-27-2011 09:53 AM

I will try the fatsort idea. I assumed that fatsort was a windows thing when I saw it. I didn't read deep enough. The rename feature of Gwenview and Digikam does a good job of providing zero-filled, incremental, numbered names as well.


All times are GMT -5. The time now is 12:50 AM.