1

I have created two files: sample.txt and sample.txt  (the second file contains some hidden characters, e.g. a space). How can I remove the latest modified file? I'm using Linux.

  • 1
    rm "sample.txt " – user156990 Mar 21 '16 at 23:22
  • thanks for your response but i just want to delete latest file without the help of filename – teja Mar 21 '16 at 23:26
  • 1
    What do you mean by "latest"? Most recently created? – user156990 Mar 21 '16 at 23:27
  • yeah. most recently created file with same file name. – teja Mar 21 '16 at 23:31
  • two files with the same name in one directory? oO – sinclair Mar 21 '16 at 23:33
2

stat is the main ingredient in this recipe: remove the echo if you're satisfied it's working

echo rm "$(stat -c "%Y:%n" * | sort -t: -n | tail -1 | cut -d: -f2-)"

You don't specify your platform: this is Linux and GNU tools.

Note that this doesn't work if the file name contains a newline.

  • xargs discards space (as mentioned by the OP) and also quotes and backslash (not mentioned) from the arguments it parses and passes. With GNU xargs and one value per line (as here) this can be fixed with -d'\n' – dave_thompson_085 Mar 22 '16 at 2:09
2

The simple and reliable way to delete the latest file in the current directory is

zsh -c 'rm ./*(om[1])'

Of course, if you're running zsh, that's just

rm ./*(om[1])

Unlike other solutions proposed in this thread such as parsing the output of ls or of stat, this works no matter what strange characters the filename contains, even unprintable characters, even newlines.

The characters in parentheses after * are glob qualifiers. om means to sort by modification time (most recent first), and [1] means to select only the first file (after sorting).

If what you want is to get rid of a particular file, relying on the modification time is a complicated approach. Instead, type rm Space Tab and navigate through the completions that your shell offers until you hit the right file.

1

If you wish to remove the latest file in a directory named dir, and the file name doesn't contain a newline character, do this:

rm -i -- "$(LC_CTYPE=C ls -t dir | head -1)"

Beware that if the file name contains unprintable characters, this may not work because ls may mangle the unprintable characters.

If the latest file in the directory is another directory you'll get an error such as rm: cannot remove ‘dir2’: Is a directory.

  • OP already said the filename contains special characters, which won't work with ls. – Thomas Dickey Mar 22 '16 at 0:15
  • @ThomasDickey anything but newline (which wasn't mentioned) is fine for ls; the problem for space etc is unquoted command substitution, which can be fixed by quoting it. Also note this selects the last modified file, which is not necessarily the last created. And on older filesystems, it's not reliable if the files were modified/created within the same second. – dave_thompson_085 Mar 22 '16 at 2:00
0

There is no (portable) direct way to do this. But if one of the solutions in Unix/Linux find and sort by date modified (which has no accepted answer) works for you, then you would do something like

rm -f "$(find-sorted-list | head -n 1)"

where find-sorted-list may include a timestamp that has to be trimmed from the front of the line, e.g., with a stage involving sed.

sed -e 's/^[^ ]* //'

for just digits and colons.

Since the question specified that the filename contains a space (among other characters), a solution using xargs seems to be ruled out.

0

Here's a shell function that relies on the stat utility; call it with an optional directory parameter (it defaults to ., the current directory), and it will execute an interactive rm of the oldest file. To throw some caution to the wind, remove the -i flag to rm. It intentionally skips directories, and so investigates only files in the given directory. In order to deal cleanly with empty directories, I added some shopt workarounds. This should, however, deal (as well as it can) with files that have spaces and newlines in their names.

function rmoldest {
  shoptnow=$(shopt -p nullglob)
  shopt -s nullglob
  tstamp=$(date +%s)
  file=
  dir=$1
  dir=${dir:-.}

  for f in "$dir"/*
  do
    if [ ! -d "$f" ]
    then
      y=$(stat -c "%Y" "$f")
      if [ $y -lt $tstamp ]
      then
        file="$f"
        tstamp=$y
      fi
    fi
  done
  $shoptnow
  if [ -n "$file" ]
  then
    /bin/rm -i "$file"
  fi
}

Here's a sample run (the leading $ are my shell prompts, do not type them):

$ touch sample.txt; sleep 1; touch 'sample.txt '

$ ls -l
total 0
-rw-r--r-- 1 Jeff None 0 Mar 21 22:02 sample.txt
-rw-r--r-- 1 Jeff None 0 Mar 21 22:02 sample.txt

$ rmoldest
/bin/rm: remove regular empty file ‘./sample.txt’? y

$ ls -l
total 0
-rw-r--r-- 1 Jeff None 0 Mar 21 22:02 sample.txt

$ rmoldest
/bin/rm: remove regular empty file ‘./sample.txt ’? y

$ ls -l
total 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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