30

This is the default behaviour of ls

ls /net/nas/data/languages/pypm/sites/rex/free/2.6/*/pool/v/vi/virtual*1.4.4*pypm
/net/nas/data/languages/pypm/sites/rex/free/2.6/linux-x86/pool/v/vi/virtualenv-1.4.4_linux-x86_2.6_1.pypm
/net/nas/data/languages/pypm/sites/rex/free/2.6/linux-x86_64/pool/v/vi/virtualenv-1.4.4_linux-x86_64_2.6_1.pypm
/net/nas/data/languages/pypm/sites/rex/free/2.6/macosx/pool/v/vi/virtualenv-1.4.4_macosx_2.6_1.pypm
/net/nas/data/languages/pypm/sites/rex/free/2.6/win32-x86/pool/v/vi/virtualenv-1.4.4_win32-x86_2.6_1.pypm

How do I make ls print only the basename? Like:

ls $OPTIONS /net/nas/data/languages/pypm/sites/rex/free/2.6/*/pool/v/vi/virtual*1.4.4*pypm
virtualenv-1.4.4_linux-x86_2.6_1.pypm
virtualenv-1.4.4_linux-x86_64_2.6_1.pypm
virtualenv-1.4.4_macosx_2.6_1.pypm
virtualenv-1.4.4_win32-x86_2.6_1.pypm

Note: I prefer shell globbing over using find as /net/nas/data/languages/pypm/sites/rex/free contains huge number of files and directories.

2
  • 1
    you prefer shell globbing OVER using find when the directory contains lots of files? typo??
    – akira
    Aug 10, 2010 at 15:24
  • 2
    I'm guessing that the OP doesn't want a listing of subdirectories, and is unaware of the option of passing -maxdepth 1 to find.
    – intuited
    Aug 10, 2010 at 16:12

8 Answers 8

27

While xargs -0 is intended to be used for input delimited by \0 (like find -print0), ls has no such option to delimit its output in this way.

However,

ls -1 /path/glob | tr '\n' '\0' | xargs -0 -n 1 basename

would do the trick to convert newlines to nulls along the way. This then allows xargs to work with names that have spaces.

EDIT: added -n 1 to xargs

8
  • This does not work for me: basename: extra operand \033[0m/net/nas/data/languages/pypm/sites/rex/free/2.6/macosx/pool/v/vi/virtualenv-1.4.4_macosx_2.6_1.pypm\033[0m'` Jan 20, 2010 at 0:07
  • @Sridhar: you might need the -n 1 you suggested elsewhere as an option to xargs ? (answer edited) Jan 20, 2010 at 0:35
  • Although I personally prefer my own answer (as I almost never have to deal with spaces in filenames), I will mark this as the answer for it handles spaces as well. Jan 20, 2010 at 7:36
  • If the mac version of xargs supports the -d (delimiter) option, you can do ls ... | xargs -d '\n' -n 1 basename.
    – intuited
    Aug 10, 2010 at 16:14
  • Would have thought just --- $ ls | xargs basename --- but found it problematic. This works.
    – Cymatical
    Sep 19, 2021 at 23:39
14

I use this:

ls | tr '\n' '\n'

It gives a list like:

file1.mp3
file2.mp3
file3.mp3
...
3
  • 4
    This is essentially the same as ls -1 (and coloring disabled), as ls implies those when not writing to a terminal. It looks like you're missing the point a bit, as the issue is stripping the dir name swhen specifying ls path arguments using wild cards. Try ls -d "$PWD/"* | tr '\n' '\n' to see what the actual issue is.
    – Daniel Beck
    Oct 8, 2012 at 19:45
  • 3
    -1 – not sure why people keep upvoting this answer. Not only does it do the same thing as ls -1, it also does not work when globs have been used, as Daniel Beck pointed out.
    – slhck
    Aug 8, 2017 at 12:43
  • -1 - This is the same as ls -1, and only works in the current directory, not with a path like ls path/*.
    – SineSwiper
    Sep 12, 2019 at 15:44
10

Both GNU basename and FreeBSD basename accept an -a argument allowing you to pass multiple paths to the command. This works great with shell globbing.

basename -a /path/glob*
6
ls -1 <path> | sed 's#.*/##'
2
  • AH! Finally something that works with multiple arguments!
    – Mmmh mmh
    Sep 16, 2014 at 9:27
  • much more performant than the accepted basename solution
    – verboze
    Mar 25, 2022 at 3:02
4

awk solution:

ls -1 /path/glob | awk -F'/' '{print $NF}'
2

ls [optional path]| xargs -0 basename

1
  • 2
    -1: ls can't delimit names by \0 which is what xargs -0 is looking for. Jan 19, 2010 at 20:49
1

You said you prefer globbing over find, but did you know that the two are not mutually exclusive? Globbing happens on any command you run, not just ls. For example:

$ export BASE=/net/nas/data/languages/pypm/sites/rex/free/2.6

$ echo $BASE/*/pool/v/vi/virtual*1.4.4*pypm | xargs basename
$ ls $BASE/*/pool/v/vi/virtual*1.4.4*pypm | xargs basename
$ find $BASE/*/pool/v/vi/virtual*1.4.4*pypm -print0 | xargs -0 basename

Notice that the find example can make use of -print0 which handy if your paths contain whitespace (the tr-based solutions mentioned elsewhere work great on normal spaces, but not on files containing actual newlines).

Lastly, if you have access to GNU find, you can also use -printf which avoids the basename call altogether:

$ find $BASE/*/pool/v/vi/virtual*1.4.4*pypm -printf '%f\n'
2
  • Unfortunately, -printf option is not available in MacOSX version of find. Jan 20, 2010 at 3:02
  • Good call; apologies for the oversight. I've updated the answer. Jan 21, 2010 at 23:37
-1

By using cut command:

ls -l |cut -d ' ' -f9
1
  • 1
    (1) Have you tried this?  (2) Try it with directories and wildcards on the command line, like in the question; e.g., ls vacation/*.jpg.  (3) If you still think this is a good answer, try it with files with spaces in their names. Jan 17, 2021 at 2:28

You must log in to answer this question.

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