How to sort by specific 'field' in filename
like this:ls | sort -t '_' -k 2
-t is separator and -k is column
Linux - Sort files by part of name (no delimiters)
This will do the sort:
sort -k1.1,1.8 -k1.9n
That defines two keys, the first one being a fixed-length 8-character key (field one, characters 1 through 8), and the secondary key being a numeric key starting at field one character 9 (and extending to the end of the line).
Numeric sorting uses whatever number it finds at the beginning of the key, so you don't need to get more sophisticated. But if you want to be more precise, you could tell sort
to use .
to delimit fields, and then use three keys:
sort -t. -k1.1,1.8 -k1.9,1n -k2
You might need this with a POSIX-standard sort
utility, if your filenames have varying extensions and you want the extensions to affect the sort. GNU sort
(used on Linux) appears to use the entire key in a numeric sort, but the POSIX standard suggests that a numeric sort key consists only of the numeric part.
Unix - Find and Sort by part of filename
You can do it in a pipeline like this:
# List files
ls |
# Include the sorting key in the front as well
sed -E 's/^(.*)([0-9]+)\.txt$/\2\t\1\2.txt/' |
# Sort on the sorting key
sort -n |
# Remove the sorting key
cut -f2-
# Grab the first letter
cut -c1
Output:
D
C
A
B
E
Bash sort files by filename containing year and abbreviated month
Try this command:
ls dir1/dir2/dir3/file_name_2017_v_*.exp.var.txt | sort -t '.' -k 1.33,1.36n -k 2,2M
Or use _
as the field-separator:
ls dir1/dir2/dir3/file_name_2017_v_*.exp.var.txt | sort -t '_' -k 5.1,5.4n -k 5.6,5.8M
If years that are different before and after the v
, need to add another -k
:
ls dir1/dir2/dir3/file_name_*_v_*.exp.var.txt | sort -t '_' -k 3.1,3.4n -k 5.1,5.4n -k 5.6,5.8M
Example(Update):
$ mkdir -p dir1/dir2/dir3
$ touch dir1/dir2/dir3/file_name_2017_v_201{5..7}.{Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec}.exp.var.txt
$ ls dir1/dir2/dir3/file_name_2017_v_*.exp.var.txt | sort -t '.' -k 1.33,1.36n -k 2,2M
$ ls dir1/dir2/dir3/file_name_2017_v_*.exp.var.txt | sort -t '_' -k 5.1,5.4n -k 5.6,5.8M
dir1/dir2/dir3/file_name_2017_v_2015.Jan.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Feb.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Mar.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Apr.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.May.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Jun.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Jul.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Aug.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Sep.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Oct.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Nov.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2015.Dec.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Jan.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Feb.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Mar.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Apr.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.May.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Jun.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Jul.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Aug.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Sep.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Oct.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Nov.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2016.Dec.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Jan.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Feb.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Mar.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Apr.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.May.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Jun.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Jul.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Aug.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Sep.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Oct.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Nov.exp.var.txt
dir1/dir2/dir3/file_name_2017_v_2017.Dec.exp.var.txt
P.S. You need to count the start and end index of the month, e.g. its 1.33,1.36n
in your example.
Finding and sorting unique file names regardless of parent folder name
Print the file name with and without its directory, sort -u
on just the file name, then remove the file name so only the full path shows.
$ find ~/Parent -name '*.txt' -printf '%f\t%p\n' | sort -k1,1 -u | cut -f 2-
~/Parent/A/a.txt
~/Parent/A/b.txt
~/Parent/C/c.txt
~/Parent/C/d.txt
Note that this will decide conflicts arbitrarily since find
prints file names in no particular order. If you want to always use the first or the last duplicate files, add an extra sort
or sort -r
call:
Always use the first:
$ find ~/Parent -name '*.txt' -printf '%f\t%p\n' | sort | sort -k1,1 -u | cut -f 2-
Always use the last:
$ find ~/Parent -name '*.txt' -printf '%f\t%p\n' | sort -r | sort -k1,1 -u | cut -f 2-
Bash and sort files in order
ls data_* | sort -n -t _ -k 2
-n: sorts numerically
-t: field separator '_'
-k: sort on second field, in your case the numbers after the first '_'
How to sort files in some directory by the names on Linux
The idiomatic way to sort something in C is to use the qsort()
function. For this to work, it's best if you can arrange to have all the file names collected into an array of pointers, and then you sort the array.
This is not too hard, but it does require either a bit of dynamic-array management, or that you introduce static limits on things (maximum length of filenames, maximum number of files).
How can I sort file names by version numbers?
Edit: It turns out that Benoit was sort of on the right track and Roland tipped the balance
You simply need to tell sort
to consider only field 2 (add ",2"):
find ... | sort --version-sort --field-separator=- --key=2,2
Original Answer: ignore
If none of your filenames contain spaces between the hyphens, you can try this:
find ... | sed 's/.*-\([^-]*\)-.*/\1 \0/;s/[^0-9] /.&/' | sort --version-sort --field-separator=- --key=2 | sed 's/[^ ]* //'
The first sed
command makes the lines look like this (I added "10" to show that the sort is numeric):
1.9.a command-1.9a-setup
2.0.c command-2.0c-setup
2.0.a command-2.0a-setup
2.0 command-2.0-setup
10 command-10-setup
The extra dot makes the letter suffixed version number sort after the version number without the suffix. The second sed
command removes the prefixed version number from each line.
There are lots of ways this can fail.
Related Topics
How to Run Multiple Programs in a Sequence
Bash -C Variable Does Not Get Assigned
Print Differences of File1 to File2 Without Deleting Anything from File2
Phusion Passenger Nginx Module Installer V3.0.17 Issue on Debian 6.0.5 Amd64 Due to Broken Package
Using Gzip to Compress Files to Transfer with Aws Command
How to Ask Bash for the Current Options
Allocating a Data Page in Linux with Nx Bit Turned Off
Script to Get User That Has Process with Most Memory Usage
How to Create a Bash Variable Like $Random
Linux Script- Date Manipulations
Resolve Relative Relocations in Partial Link
Find Command Find Directories That Were Created After a Certain Date Under Linux/Cygwin
How to Start/Restart/Stop Apache Server on Linux as Non-Root User
Shell Script to Delete Files When Disk Is Full
Why Does Bash Behave Differently, When It Is Called as Sh