1

I have a directory containing several files. I need to know the full path of only the most recent file that contains a certain string.

This needs to work on macOS, and the directory path contains spaces.

I need to be able to invoke this bash command without having to cd into that directory first.

Note: I've seen similar questions posted here, but they are only checking if the most recent file in a directory contains that string. This means it will fail if the second-most-recent file in the directory is the one that contains the string I'm looking for.

Part of the reason I'm struggling is that things break when directories have spaces in them, and figuring out how to quote paths is non-trivial with xargs. Using find -exec doesn't work because there is no find flag to return results in last-modified order.

Clarifications: The file's contents need to contain the string, not the filename. I'm looking to use bash, as this is part of other bash scripts, and I'm also keen to understand how to do this in bash.

1
  • 2
    Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.
    – Community Bot
    Commented Jun 28, 2023 at 11:13

2 Answers 2

6

If that string is to be found in the name of the file:

print -rC1 -- the/directory/**/*string*(Nom[1])

If it's in the contents:

for f (the/directory/**/*(N.om)) grep -l -- string $f && break

(assuming the zsh shell which should be the default interactive shell on macos, not bash which on macos is an ancient version and anyway doesn't have glob qualifiers).

The om glob qualifier orders the glob expansion by modification time (from newest to oldest), . restricts to regular files, N for Nullglob. Add :P if you need an absolute path to those files.

See info zsh qualifiers (or the same online for the latest version of zsh) for details.

In bash, sh or other shells, you can always do:

zsh -c 'any of those codes above'
2
  • Thanks, this is great. I should have specified more strongly that I was looking for a bash approach, mainly because this is part of a set of bash scripts I need to write, and it'd be messy to switch between bash and zsh. Is a bash approach massively more complicated? Commented Jun 28, 2023 at 12:36
  • @AndrewParks, in bash or any shell, use zsh -c 'the code in there' Commented Jun 28, 2023 at 12:42
3

Mac OS brings zsh, so no need for find or anything complex. See man zshexpn, pretty much at the end

# Usage:
# findnewest path string
# 
function findnewest() {
  ## look recursively **; if you want only top-level files, remove the **/.
  for file in $1/**/*(.Nom) ; # (om): order by modification date, youngest first
    if grep -q -F -- "$2" "${file}" ; then
      # you said you needed the full path:
      realpath -- "${file}"
      break
    fi
  done
}
0

You must log in to answer this question.

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