LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 06-08-2012, 05:25 AM   #1
linux_
LQ Newbie
 
Registered: Mar 2010
Location: Pune, India
Distribution: Fedora, CentOS, Ubuntu
Posts: 24

Rep: Reputation: 1
Arranging files in a directory


Hello,
I have a directory, say dir. It contains numbered files such as
1.abcd.php
2.gfgf.php
3.dff.pdf
10.dfsdf.php

The order of these files in dir is
1.abcd.php
10.dfsdf.php
2.gfgf.php
3.dff.pdf
Which is obvious.

Is it possible to permanently arrange these files in order based on numbers?
 
Old 06-08-2012, 05:51 AM   #2
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian i686 (solaris)
Posts: 8,491

Rep: Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429
how do you know the order of the files in this dir? Why is it so obvious?
 
Old 06-08-2012, 06:15 AM   #3
linux_
LQ Newbie
 
Registered: Mar 2010
Location: Pune, India
Distribution: Fedora, CentOS, Ubuntu
Posts: 24

Original Poster
Rep: Reputation: 1
Well, you can check the order with ls.
It lists the files in alphabetic order.
But I don't want to list, I want to arrange it based on numbers.

It is obvious because the file system arranges the files in alphabetic order.
 
Old 06-08-2012, 06:17 AM   #4
whizje
Member
 
Registered: Sep 2008
Location: The Netherlands
Distribution: Slackware64 current
Posts: 592

Rep: Reputation: 140Reputation: 140
A possible solution is move the files to a temp directory and move them back in the desired order.

Last edited by whizje; 06-08-2012 at 06:19 AM.
 
Old 06-08-2012, 06:55 AM   #5
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian i686 (solaris)
Posts: 8,491

Rep: Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429Reputation: 2429
yes, the correct answer is #4, move the files into another directory and move them back in the desired order. ls will sort alphabetically by default - it is obvious, the real order of the files is not arranged by the filesystem. It simply stores the entries. You can check it by ls -U, see the man page.
What you need is to sort those entries as numbers. ls cannot do it, so you need to pipe the result across sort. See the man page to find out how can you make a numeric sort.




_____________________________________
If someone helps you, or you approve of what's posted, click the "Add to Reputation" button, on the left of the post.
Happy with solution ... mark as SOLVED
(located in the "thread tools")
 
Old 06-08-2012, 07:02 AM   #6
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738
first, the "order in the directory" has no real meaning---the files are in random location based on the order in which they were created and where the file system found available space. I think you mean to say---"the order in which they are listed".

If the filenames all have numbers at the front, then it appears that this works:
ls |sort -n
but this simple solution will not work with ls -l

It might help to know why you want to do this---what problem are you trying to solve?
 
Old 06-08-2012, 07:23 AM   #7
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738
My post above was in typing while pan's was posted--sorry for the overlap.

I'm missing how moving the files to another directory will help----"ls" still lists alphabetically by filename
 
Old 06-08-2012, 10:51 AM   #8
414N
Member
 
Registered: Sep 2011
Location: Italy
Distribution: Slackware
Posts: 635

Rep: Reputation: 186Reputation: 186
I assembled this script because this is a problem which I seldom encounter too, so I thought it was time to put together a reusable solution.
The script should be called from within the directory containing the files to be renamed. It can accept an optional argument which is a hint to at how many digits you want your numbers to be padded to; it's a hint because the script already computes the minimum required length to correctly pad all the files contained in the directory and uses the user supplied value only if it's greater than the computed value.
It's also possible to go back to a minimum padding if the user previously used an unnecessarily high argument.
BIG PHAT WARNING: i tested the script on a bunch of automatically generated files so, before using this script to alter real-world files, please backup your data.
Code:
#!/bin/sh
# 0 pad filenames starting with a number in the current directory
# Copyright 2012 Alan Alberghini <414N@slacky.it>
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# This script renames a bunch of files in the current directory matching 
# FILE_PATTERN adding prepending 0s to their numbers in order to see them
# sorted in directory listings etc.
# Script arguments:
# $1 - (OPTIONAL) number of digits that the number inside the filename should
#      have. It's used only if its value is greater than the value 
#      automatically computed from the number of files in the directory.

# The regex corresponding to the files to be renamed.
FILE_PATTERN='^[0-9]+'

# Function rename_file
# Renames the given file with the correct 0-padding
# Arguments:
# $1 - filename of the file to rename
function rename_file()
{
	# Extract the number part from the filename using FILE_PATTERN
	NUMBER=`echo "$1" | egrep -o $FILE_PATTERN`

	# Extract the number of significant digits
	NUMBER_TRIMMED=$(seq $NUMBER $NUMBER)

	# Store the remainder of the file name
	FILE_REMAINDER="`echo "$1" | sed -e "s|$NUMBER||"`"

	# If the extracted NUMBER has less significant digits than NUM_DIGITS,
        # the file is renamed.

	if [ ${#NUMBER_TRIMMED} -le $NUM_DIGITS ]
	then
		mv "$1" `printf %0${NUM_DIGITS}d $(( 10#$NUMBER ))`"$FILE_REMAINDER"
	fi
}
# This variable contains the number of 0s wanted by the user, or 0 if not
# specified
NUM_ZERO_USR=${1:-0}

# The modified regex for find. find expects a regex string matching the entire
# path, so, for searching in current directory, './' has to be prepended to
# the pattern string, as '.*' has to be appended to match the rest of the
# filename
FIND_FILE_PATTERN=`echo $FILE_PATTERN | sed -e 's|\^|\^./|'`'.*'

# The find command which will be used hereon.
FIND_BASECOMMAND="find . -type f -maxdepth 1 -regex $FIND_FILE_PATTERN"

# The number of files that need to be renamed. We only look to files matching
# FILE_PATTERN
NUM_FILES=`$FIND_BASECOMMAND | wc -l`

# Compute the number of digits needed to count every file. It is done as:
# Ceiling(Log(10, NUM_FILES))
# where:
# Ceiling is the function which returns the minum integer which is greater than its argument;
# Log(10, NUM_FILES) is the logarithm to base 10 of NUM_FILES
# Given that bc lacks a ceiling function, we discard the decimal part of the
# result and then add 1 to it.
NUM_DIGITS_NEEDED=$((`echo "l($NUM_FILES)/l(10)" | bc -l | cut -d. -f1`+1))

# If the number of digits specified by the user is greater than what has been
# extracted from the number of files, then we'll use the user value hereon.
if [ $NUM_ZERO_USR -gt $NUM_DIGITS_NEEDED ]
then
	NUM_DIGITS=$NUM_ZERO_USR
else
	NUM_DIGITS=$NUM_DIGITS_NEEDED
fi

echo "Going to rename $NUM_FILES files, padding numbers to $NUM_DIGITS inside current directory ."

$FIND_BASECOMMAND -exec basename {} \; | while read FILE; do rename_file "$FILE"; done
 
Old 06-08-2012, 01:11 PM   #9
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958Reputation: 1958
I also have a script that pads 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}"	#Use environment defaults if they exist.
#BRED="${BRED:-\e[1;31m}"	#set the COLOR variable below to the desired one
#BBLUE="${BBLUE:-\e[1;34m}"
#BMAGENTA="${BMAGENTA:-\e[1;35m}"
RESET="${RESET:-\e[0m}"

COLOR=$BCYAN			#choose which color to use here
#set default padding level
pad=2


# Set up the help dialog
help(){
	local -a help
	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.'	)
	help+=( '' 																				)
	help+=( "\tUsage: \t${COLOR}${0##*/} [-n <num>] <files>${RESET}"										)
	help+=( "\t\t${COLOR}${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+=( '' 																				)
	help+=( '\t-h prints this help message'															)
	help+=( '' 																				)

	local IFS=$'\n'
	echo -e "${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) help >&2
             exit "2"
          ;;

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

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

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

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

# Process files in input parameters
re='([^[0-9]*)([0-9]+)(.*)'

for file ; do

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

	# Split filename into prefix-digits-suffix
	[[ "$file" =~ $re ]]

	# 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 "${COLOR}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*)  	for i in "${!oldfile[@]}" ; do
					mv -n "${oldfile[i]}" "${newfile[i]}"
				done
				echo
				;;

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

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

fi

exit 0
One advantage of mine is that you can pass it a list of files to work on, instead of just the directory. And if you use "-n 1", it will remove all zero-padding. On the other hand, it only operates on the first number string in the filename at this point.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Auto Arranging Windows in XFCE4 cram869 Linux - Desktop 1 03-04-2011 08:25 AM
Arranging Files In Alphabetical order swatward Linux - General 4 12-11-2006 09:14 PM
Re-arranging a hard disk silkenphoenixx Linux - Software 5 10-13-2006 02:27 PM
Partition re-arranging, Imaging and Linux 1kyle Linux - Software 0 03-17-2004 04:06 AM
Dual bootup. Arranging order amoskoh Linux - General 1 01-25-2003 01:41 PM


All times are GMT -5. The time now is 05:18 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration