<> == How can I get the newest (or oldest) file from a directory? == This page should be merged with [[BashFAQ/003]] The intuitive answer of `ls -t | head -1` is wrong, because parsing the output of `ls` is [[ParsingLs|unsafe]]; instead, you should create a loop and compare the timestamps: {{{ # Bash files=(*) newest=${files[0]} for f in "${files[@]}"; do if [[ $f -nt $newest ]]; then newest=$f fi done }}} Then you'll have the newest file (according to modification time) in `$newest`. To get the oldest, simply change `-nt` to `-ot` (see `help test` for a list of operators), and of course change the names of the variables to avoid confusion. Bash has no means of comparing file timestamps other than `mtime`, so if you wanted to get (for example) the most-recently-accessed file (newest by `atime`), you would have to get some help from the external command `stat(1)` (if you have it) or the [[BashLoadableBuiltins|loadable builtin]] `finfo` (if you can load builtins). Here's an example using `stat` from GNU coreutils 6.10 (sadly, even across Linux systems, the syntax of `stat` is not consistent) to get the most-recently-accessed file. (In this version, `%X` is the last access time.) {{{ # Bash, GNU coreutils newest= newest_t=0 for f in *; do t=$(stat --format=%X -- "$f") # atime if ((t > newest_t)); then newest_t=$t newest=$f fi done }}} This also has the disadvantage of spawning an external command for every file in the directory, so it should be done this way only if necessary. To get the oldest file using this technique, you'd either have to initialize `oldest_t` with the largest possible timestamp (a tricky proposition, especially as we approach the year 2038), or with the timestamp of the first file in the directory, as we did in the first example. Here is another solution spawning an external command, but posix: {{{ # posix unset newest for f in ./*; do # set the newest during the first iteration newest=${newest-$f} #-prune to avoid descending in the directories, the exit status of find is useless here, we check the output if [ "$(find "$f" -prune -newer "$newest")" ]; then newest=$f fi done }}} Example: how to remove all but the most recent directory. (Note, the modification time on a directory is the time of the most recent operation which ''changes'' that directory -- meaning the last file creation, file deletion, or file rename.) {{{ $ cat clean-old dirs=(enginecrap/*/) newest=${dirs[0]} for d in "${dirs[@]}" do if [[ $d -nt $newest ]] then newest=$d fi done for z in "${dirs[@]}" do if [[ "$z" != "$newest" ]] then rm -rf "$z" fi done $ for x in 20101022 20101023 200101025 20101107 20101109; do mkdir enginecrap/"$x";done $ ls enginecrap/ 200101025 20101022 20101023 20101107 20101109 $ ./clean-old $ ls enginecrap/ 20101109 }}} ---- CategoryShell