14

My folder parent has the following content:

A.Folder B.Folder C.File

It has both folders and files inside. B.Folder is newer. Now I just want to get B.Folder, how could I achieve this? I tried this,

ls -ltr ./parent | grep '^d' | tail -1

but it gives me drwxrwxr-x 2 user user 4096 Jun 13 10:53 B.Folder, but I just need the name B.Folder.

  • 1
    use this ls -ltr ./parent | grep '^d' | tail -1| awk '{print $NF}' – بارپابابا Jun 13 '14 at 15:36
  • Using awk works, but I want to see if there is a cleaner solution. :) – Daniel Jun 13 '14 at 15:44
  • find . -maxdepth 1 -type d | TZ=utc xargs ls -ld --full-time | sort -k 6 – ctrl-alt-delor Jun 13 '14 at 16:18
23

Try this:

$ ls -td -- */ | head -n 1

-t options make ls sort by modification time, newest first.

If you want remove /:

$ ls -td -- */ | head -n 1 | cut -d'/' -f1
  • 1
    How to get rid of slash /? – Daniel Jun 13 '14 at 15:39
  • This does not work if you are in another folder. I mean ls -td -- ./parent | head -n 1 does not give me the correct results, do I HAVE TO use subshell such as cd ./parent every time and execute this command? Any solution? – Daniel Jun 13 '14 at 16:02
  • @Daniel: You must run my answer in current working directory to make it works. Otherwise, you must use a relative path like Herson's answer. – cuonglm Jun 13 '14 at 17:22
  • Removing last / doesn't work. Example: /home/cuo/bin/ Expected: /home/cuo/bin – Marius Andreiana Aug 11 '17 at 8:34
5
ls -td -- ./parent/*/ | head -n1 | cut -d'/' -f2

Difference to Herson's solution is the slash after *, which makes the shell ignore all non-dir files. Difference to Gnouc, it'll work if you are in another folder.

Cut needs to know the number of parent directories (2) in order to delete trailing '/'. If you don't have that, use

VAR=$(ls -dt -- parent/*/ | head -n1); echo "${VAR::-1}"
3

Obligatory zsh answer:

latest_directory=(parent/*(/om[1]))

The characters in parentheses are glob qualifiers: / to match only directories, om to sort matches by increasing age, and [1] to retain only the first (i.e. newest) match. Add N if you want to get an empty array (normally you get a 1-elementy array) if there is no subdirectory of parent.

Alternatively, assuming that parent doesn't contain any shell globbing character:

latest_directory='parent/*(/om[1])'; latest_directory=$~latest_directory

If you don't have zsh but you have recent GNU tools (i.e. non-embedded Linux or Cygwin), you can use find, but it's cumbersome. Here's one way:

latest_directory_inode=$(find parent -mindepth 1 -maxdepth 1 -type d -printf '%Ts %i\n' | sort -n | sed -n '1 s/.* //p')
latest_directory=$(find parent -maxdepth 1 -inum "$latest_directory_inode")

There's a simple solution with ls, which works as long as no directory name contains newlines or (on some systems) non-printable characters:

latest_directory=$(ls -td parent/*/ | head -n1)
latest_directory=${latest_directory%/}
1

You can do:

ls -td -- ../parent/* | head -n 1
  • This gives the latest file. Daniel only wants directories. – Gilles Jun 14 '14 at 22:44
0

Following command will do the job even in case of directory name containing space :

cp `find . -mindepth 1 -maxdepth 1 -type d  -exec stat --printf="%Y\t%n\n" {} \;  |sort -n -r |head -1 |cut -f2'`/* /target-directory/.

The updated explanation of the stuff in the backticks is:

  • . - the current directory (you may want to specify an absolute path here)
  • -mindepth/-maxdepth - restrict the find command only to the immediate children of the current directory
  • -type d - only directories
  • -exec stat .. - outputs the modified time and the name of the directory from find separated with a tab (and not a space)
  • sort -n -r |head -1 | cut -f2 - date orders the directory and outputs the entire name of the most recently modified (even if containing some space as cut default delimiter tab)

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.