0

I need to create a bash script on a linux box (centos 7) to sort some files using the number which is at the start of the file name and then save this to a list variable so that i can match the full file name to a number that the user is prompted to enter when the script is run.

However the files are named in an inconsistent manner.

The first part of the file name is a number and the second part is text however some of the files have a . (period/full stop) separating the number part of the file name and the text part, and some do not, and some have leading zeros and some do not e.g:

001file.txt
2.file.txt
03file.txt
022.file.txt
28file.txt 

At first I was thinking that I may need to use Regular expressions to perform the sorting of these files however its been pointed out to me that this would not work as the file names are irregular so I am wondering if there is a built in function within bash that I would be better off using...

Any advice or pointers would be much appreciated...

  • 1
    So you have a collection of files with an irregular numbering pattern and want to use a regular expression to try to sort them? Secondly, regular expressions are a searching tool; not a sorting tool. And firstly, in order to sort thing they do need to be in something resembling a pattern in the first place. Finally, you might have some success using sort -n or sort --version perhaps. – DopeGhoti Jul 31 '18 at 22:53
  • Thank you for pointing that out - as you may have gathered I am not very experienced in this sort of thing... editing my question... – Mark Smith Jul 31 '18 at 22:56
  • 1
    @MarkSmith Is your example how you want the filenames to appear when they are sorted? – Nasir Riley Aug 1 '18 at 0:23
  • 1
    Hehe... "in this sort of thing"......... Sorry, my humor. Anyway, how do you want the files to be ordered? Should files with a leading 0 be all first or should leading zeros be ignored in the sorting? – confetti Aug 1 '18 at 0:44
  • Would the user enter 022 or 22? – Jeff Schaller Aug 1 '18 at 2:13
0
#!/bin/bash

# declare the arrays for the files and the sorting
declare -A files
declare -A sorting

# get a list of filenames into it, saving number without 0's as key
for file in *; do
    fnum=$(echo "$file" | tr -d -c 0-9 | sed 's/^0*//')
    files[$fnum]="$file"
    sorting[$fnum]=$fnum
done

# sort the array by its numeric key values
IFS=$'\n' sorted=($(sort -n <<<"${sorting[*]}"))
unset IFS

# check for user input and if its numerical
if [[ $1 =~ ^-?[0-9]+$ ]]; then
    # iterate through the array
    for i in "${sorted[@]}"; do
        # only handle files above user input number
        if [[ $i -gt $1 ]]; then
            # execute your sql here, echo is just for debugging
            echo ${files[$i]}
        fi
    done
else
    echo "Please supply a number as argument"
    exit 1
fi

This script is saving every file in the current directory in an associative array, using the number in the file as the key of every item and the corresponding filename as its value. Note that tr extracts ALL the numbers from the filename, so 02.test.3.txt would become 23. Leading zeros are being ignored.


Using your files as tests in a folder and running the script as ./test.sh 2 it outputs this:

03file.txt
022.file.txt
28file.txt
  • It's better to wait until there is more clarity before posting an answer. A few things aren't clear such as how he wants the files sorted, whether or not the files exist in only one directory or in one or more subdirectories, or how the script to which he's going to pass the filenames will read them. – Nasir Riley Aug 1 '18 at 1:08
  • You're right, I might've assumed too much from what I quoted. But I can still always edit my answer to fit his needs. – confetti Aug 1 '18 at 1:15
  • Thank you for your reply - I want to store and sort the files so that if the number passed to the script corresponds to the number entered by the user then an action is performed on that file and any files where the number is greater - I tried to keep my question as simple as possible but the actual problem I am trying to solve is running numbered scripts in sequence based on the number passed to the script - so if the files are numbered as above and the user passes the number 2, then 03file.txt, 022.file.txt and 28file.txt files are executed sequentially - I hope this makes sense and thanks – Mark Smith Aug 1 '18 at 11:01
  • Quite confused here. Why wouldn't 2.file.txt be "executed" too if he enters 2? Also, what do you mean by "executed", since they're text files (?). So basically you want the leading zeros to be ignored, right? And when the user enters 2 the last four files of your example list should be selected, right? And when 3 is entered only 03file.txt correct? – confetti Aug 1 '18 at 14:43
  • Sorry for the confusion - I would want to execute any files were the number in the filename is greater and next in sequence, than the number entered - so if 2 is entered then 03file.txt, 022.file.txt and 28file.txt would be executed (they are actually sql scripts rather than txt files - I had tried to make the question more simple which I realise may not have helped...) – Mark Smith Aug 1 '18 at 20:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.