Inside one of my folder I have a lot of files looks like enum-*

$ ls
PRIM         enum-00020   enum-00040   enum-00059   enum-00078   enum-00101   enum-00122   enum-00141   enum-00160   enum-00179
enum-00001   enum-00021   enum-00041   enum-00060   enum-00079   enum-00102   enum-00123   enum-00142   enum-00161   enum-00180
enum-00002   enum-00022   enum-00042   enum-00061   enum-00080   enum-00103   enum-00124   enum-00143   enum-00162   enum-00181
enum-00003   enum-00023   enum-00043   enum-00062   enum-00081   enum-00104   enum-00125   enum-00144   enum-00163   enum-00182
enum-00005   enum-00024   enum-00044   enum-00063   enum-00082   enum-00106   enum-00126   enum-00145   enum-00164   enum-00183
enum-00006   enum-00026   enum-00045   enum-00064   enum-00084   enum-00107   enum-00127   enum-00146   enum-00165   enum-00184
enum-00007   enum-00027   enum-00046   enum-00065   enum-00085   enum-00108   enum-00128   enum-00147   enum-00166   enum-00185
enum-00008   enum-00028   enum-00047   enum-00066   enum-00086   enum-00110   enum-00129   enum-00148   enum-00167   enum-00186
enum-00009   enum-00029   enum-00048   enum-00067   enum-00087   enum-00111   enum-00130   enum-00149   enum-00168   enum-00187
enum-00010   enum-00030   enum-00049   enum-00068   enum-00088   enum-00112   enum-00131   enum-00150   enum-00169   enum-00188
enum-00011   enum-00031   enum-00050   enum-00069   enum-00089   enum-00113   enum-00132   enum-00151   enum-00170   enum-00189
enum-00012   enum-00032   enum-00051   enum-00070   enum-00090   enum-00114   enum-00133   enum-00152   enum-00171   enum-00190
enum-00013   enum-00033   enum-00052   enum-00071   enum-00092   enum-00115   enum-00134   enum-00153   enum-00172   enum-layered
enum-00014   enum-00034   enum-00053   enum-00072   enum-00094   enum-00116   enum-00135   enum-00154   enum-00173
enum-00015   enum-00035   enum-00054   enum-00073   enum-00095   enum-00117   enum-00136   enum-00155   enum-00174
enum-00016   enum-00036   enum-00055   enum-00074   enum-00096   enum-00118   enum-00137   enum-00156   enum-00175
enum-00017   enum-00037   enum-00056   enum-00075   enum-00098   enum-00119   enum-00138   enum-00157   enum-00176
enum-00018   enum-00038   enum-00057   enum-00076   enum-00099   enum-00120   enum-00139   enum-00158   enum-00177
enum-00019   enum-00039   enum-00058   enum-00077   enum-00100   enum-00121   enum-00140   enum-00159   enum-00178

I would like to find the largest number of enum- and export it to a variable, say ENUM_LARGEST, which will be used in a future script. How should I write this line?

  • 1
    Can we assume that the numbers are zero-padded to the same width as shown? – muru Sep 8 '15 at 17:49
  • yep :) you can assume that – user40780 Sep 8 '15 at 17:51
  • 1
    You didn't ask this, but I'll suggest it anyway -- consider finding this value either programmatically or manually (once) and storing it in a dot-file or other "index" file so that you don't have to re-parse the whole directory every time -- simply look up that index value, increment, and re-write it. – Jeff Schaller Sep 8 '15 at 19:25
up vote 3 down vote accepted

Here's something to get you started:

ENUM_LARGEST=$(ls | sed 's/enum-//' | sort -n | tail -1)

...which will get the zero-padded value. One way to strip the leading zeros:

ENUM_LARGEST=$(ls | sed 's/enum-//' | sort -n | tail -1 | bc)

With zsh:

ENUM_LARGEST=(enum-<->(n[-1]))

The <-> glob matches any sequence of digits. The glob qualifier [-1] restricts the list of matches to the last one. The glob qualifier n causes sorting to take numeric values into account instead of lexicographic order; it doesn't make any difference here, but it would be necessary if your numbers weren't padded with zeros to the same width.

With any Bourne/POSIX-style shell, relying on the fact that the numbers are zero-padded: match all the files, and keep the last one.

set_last_match () {
  eval "$1=\${$#}"
}
set_last_match ENUM_LARGEST enum-[0-9]*

A pure bash answer :

(/home/****/test)
└-(>:) ls
toto001  toto002  toto003  toto004  toto005  toto067
(/home/****/test)
└-(>:) file=( toto* ) ; echo ${file[-1 ]#toto}
067

And another one :

(/home/****/test)
└-(>:) for last in toto*; do :; done; printf '%s\n' "${last#toto}" 
067
  • 1
    For the first one, if there is no folder starting with "toto" then command gives all files in directory which is not good. – Shibli Sep 23 at 18:03

echo enum-[0-9]* | tail -c 6

prints out all the files beginning with "enum-" and then a number, and only shows you the last 6 characters (the length of your number strings plus one for the carriage return). Relies on your shell sorting the numbers correctly (as long as everything is padded the same, it should).

You should not parse ls. Instead use echo/awk:

ENUM_LARGEST="$(echo enum-* | awk '$0=substr($NF,6)')"

The awk part printf the number of the highest file number with leading zeros(00190). substr cuts away the first 6 character (enum-).

  • 1
    echo also has pitfalls. In this case (enum_ always followed by 5 digits) I'd still suggest ls -1 | tail -1 to get the highest dir. – ott-- Sep 8 '15 at 19:16
  • 1
    I'll agree with the "don't parse ls" sentiment while also pointing out that we're dealing with known input -- specific solution for a specific problem. – Jeff Schaller Sep 8 '15 at 19:24

ENUM_LARGEST=$(ls enum-* | sort | tail -n1)

This stores the entire string, e.g. enum-00190. If you just want the number, you could add cut -c 6- to the end of that pipeline. Note this only works if the prefix is literally enum-; if you want to work with arbitrary ones, it needs a bit more bookkeeping.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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