0

Any advise on how to do delete all files and only keep the latest file in each sub-directories, starting from a specific directory? This is what I have tried:

#!/bin/bash

find /home/ftp/ -type f | while IFS= read -r line
do
  find "$line" -type f | head -n -1 | while read file
  do
    #rm -f "$file"
    echo "$file"
  done
done

I have 2 sub-directories in /home/ftp/upload and /home/ftp/download. Both sub-directories have 2 files in each of the sub-directories.

When tested the script above, there is no file name echo out.

4
  • 3
    try something yourself first... if you are new to command line and shell scripting, have a look at stackoverflow.com/documentation/bash/topics and mywiki.wooledge.org/BashGuide .. or search online, lots of them are there
    – Sundeep
    Jul 25, 2016 at 8:37
  • HINT: find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head -n1 will list the latest file name. Use this logic to develop your script. If you fails at some point, do ask.
    – SHW
    Jul 25, 2016 at 8:45
  • Edit that exact command into your question and specify what result you are getting and what result you expect.
    – Wildcard
    Jul 25, 2016 at 8:51
  • Your first find should be -type d to select the directories. Note, though, that the second find doesn't order the results so you may end up keeping files at random, rather than "latest". Jul 25, 2016 at 11:40

1 Answer 1

1

With zsh, from the current directory:

for dir (**/*(N/)) {
  files=($dir/*(N.om))
  (($#files > 1)) && echo rm -f -- $files[2,-1]
}

If you want hidden directories and files considered, add the D glob qualifier.

That only considers regular files. If you want other types of files like devices, sockets, named pipes, or if you want to follow symlinks, it can be adapted with more glob qualifiers.

Remove the echo to actually do the task.

With recent GNU tools and a POSIX shell:

(export LC_ALL=C
find . -type f -printf '%T@\t%p\0' |
  sort -rzn |
  cut -zf2- |
  gawk -v RS='\0' -v ORS='\0' '
    match($0,/.*\//) && n[substr($0,1,RLENGTH-1)]++' |
  xargs -r0 echo rm -f
)

You must log in to answer this question.

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