2

I want to find file with specific pattern and print the latest file matching the pattern with full path

find ../*.gz -type f -print0 | sort -nr | cut -d: -f2- | head -n 1

How do I print the full path of the same.

As requested by users ls -l:

ls -l
drwxrwxr-x 3 xxx xxx 4096 Jun 27 23:29 fa1caae85
drwxrwxr-x 3 xxx xxx 4096 Jun 27 23:28 ga1c93eda
drwxrwxr-x 3 xxx xxx 4096 Jun 27 23:28 la1cbbh05
drwxrwxr-x 3 xxx xxx 4096 Jun 27 23:08 node_modules
drwxrwxr-x 3 xxx xxx 4096 Jun 27 23:08 _tasks

All top three folders contains require .gz files, however I want to get latest .gz file out of them.

5
  • @Rahul, yes. I guess my pattern is *.gz
    – RaceBase
    Jun 28, 2016 at 6:49
  • 1
    You do realize that find ../*.gz doesn't make sense, right? Jun 28, 2016 at 7:06
  • @SatoKatsura, didn't get you. Can you explain plz
    – RaceBase
    Jun 28, 2016 at 7:49
  • @Rahul, I am searching for that file in sub-directories.
    – RaceBase
    Jun 28, 2016 at 7:50
  • @Rahul, yes. I updated the OP with your request
    – RaceBase
    Jun 28, 2016 at 7:56

3 Answers 3

3

Unorthodox approach:

zsh -c 'print -r $PWD/**/*.gz(.om[1])'

where

  • () after *.gz means to use so called glob qualifiers, i.e.:
  • . consider only plain files
  • om sort by modification time
  • [1] take only first element
  • add the D qualifier to also consider hidden gz files (like find does).

Obviously if you are already using zsh you don't need to call it with zsh -c.

2
  • Not using zsh. Looking for bash solutions :)
    – RaceBase
    Jun 28, 2016 at 9:56
  • 1
    There's nothing unorthodox about using a tool that supports the functionality that you require.
    – Kusalananda
    Jan 22, 2021 at 12:59
2

You can do that by using this command,

find "$(pwd)" -type f -name "*.gz" -printf "%T@ %p\n"| sort -rn | cut -d' ' -f 2- | head -n 1

That assumes GNU find, that the path names don't contain newline characters and that file names are valid text in the locale. To handle newlines and non-characters, you could change it to:

(
  export LC_ALL=C
  find "$PWD" -type f -name '*.gz' -printf '%T@\t%p\0' |
    sort -zrn | head -zn 1 | cut -zf 2- | tr '\0' '\n'
)

assuming relatively recent versions of GNU utilities. That is use NUL delimited records instead of lines (newline delimited records) as NUL is the only character that cannot occur in a file path.

We avoid command substitution ($(pwd)) which strips trailing newline characters, by using the $PWD variable (which contains the path to the current working directory in POSIX shells).

Switching the locale to C (here locally in a subshell environment (...)) ensures every byte is always considered a character (it also simplifies sorting and text processing in general).

6
  • it still prints relative path.
    – RaceBase
    Jun 28, 2016 at 9:00
  • @Reddy try updated one
    – Rahul
    Jun 28, 2016 at 9:12
  • worked out. Thanks. is it head or tail
    – RaceBase
    Jun 28, 2016 at 9:59
  • 1
    @Reddy you have used sort -nr | head -n 1 and I have just used sort -n | tail -n 1, both are one and the same thing.
    – Rahul
    Jun 28, 2016 at 11:14
  • 1
    #Rahul, missed that one char. I was just wondering myself is it head or tail. Thanks for pointing
    – RaceBase
    Jun 28, 2016 at 12:40
0

This worked nicely for me:

ls -t ../*.gz | head -n1

From man ls:

  -t                         sort by modification time, newest first

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .