简体   繁体   中英

Finding most recent file from a list of directories from find command

I use find . -type d -name "Financials" find . -type d -name "Financials" to find all the directories called "Financials" under the current directory. Since I am on Mac, I can use the following (which I found from another stackoverflow question) to find the latest modified file in my current directory: find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -rn | head -1 | cut -f2- -d" " find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -rn | head -1 | cut -f2- -d" " find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -rn | head -1 | cut -f2- -d" " . What I would like to do is find a way to pipe the results of the first command into the second command--ie to find the most recently modified file in each "Financials" directory. Is there a way to do this?

I think you could:

find . -type d -name "Financials" -print0 |
xargs -0 -I{} find {} -type f -print0 |
xargs -0 stat -f "%m %N" | sort -rn | head -1 | cut -f2- -d" "

But if you want separately for each dir, then... why not just loop it:

find . -type d -name "Financials" |
while IFS= read -r dir; do
   echo "newest file in $dir is $(
       find "$dir" -type f -print0 |
       xargs -0 stat -f "%m %N" | sort -rn | head -1 | cut -f2- -d" "
   )"
done

Nest the 2nd file+xargs inside a first find+xargs:

find . -type d -name "Financials" -print0 \
| xargs -0 sh -c '
    for d in "$@"; do
        find "$d" -type f -print0 \
        | xargs -0 stat -f "%m %N" \
        | sort -rn \
        | head -1 \
        | cut -f2- -d" "
    done
' sh

Note the trailing "sh" in sh -c '...' sh -- that word becomes "$0" inside the shell script so the for-loop can iterate over all the directories.

A robust way that will also avoid problems with funny filenames that contain special characters is:

  1. find all files within this particular subdirectory, and extract the inode number and modifcation time

    $ find . -type f -ipath '*/Financials/*' -printf "%T@ %i\\n"
  2. extract youngest file's inode number

    $ ... | awk '($1>t){t=$1;i=$2}END{print i}'
  3. search file information by inode number

    $ find . -type f -inum "$inode" '*/Financials/*'

So this gives you:

  $ inode="$(find . -type f -ipath '*/Financials/*' -printf "%T@ %i\n" | awk '($1>t){t=$1;i=$2}END{print i}')"
  $ find . -type f -inum "$inode" '*/Financials/*'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM