53

Lets say when I do ls command the output is:

file1 file2 file3 file4

Is it possible to display only a certain column of output, in this case file2? I have tried the following with no success:

echo ls | $2

Basically all I want to do is echo only the second column, in this case, I want to echo:

file2
  • 2
    What is a situation in which you really want a column of ls output? – michas Nov 18 '13 at 7:43
  • 11
    As a general rule, you should never parse ls. There are almost always better ways of getting the info you need. – terdon Nov 18 '13 at 15:43
  • I wouldn't do that stranger :P (sorry I allways liked that phrase) the number of columns depend on the names files and folders have, so 2nd column may be the one you want, or may not, or may be in one ls and after creating some files/folders it may no longer be what you want. As terdon pointed out there sure are better ways to get what you want – YoMismo Mar 16 '15 at 16:28
80

The following command will format ls output into one column

ls -1 /directory
  • 2
    But it doesn't give you just the one column the OP is interested in. – Anthon Mar 16 '15 at 15:45
  • 1
    To make it correct : ls -1 /directory | head -2 | tail -1 or ls -1 /directory | perl -ne 'print if $. == 2' – KWubbufetowicz Feb 10 '16 at 18:47
  • @KWubbufetowicz ls | sed -n '1p;q' seems simpler – Fiximan Feb 22 '16 at 14:46
  • 3
    The answer I was looking for, but not for the question of OP. – Michael Lang Feb 1 '17 at 8:56
36

You're looking for this:

ls -C | awk '{ print $2 }'

However, assuming you're going to try and use this filename later, don't do this, as it will break on filenames containing whitespace. Instead, put the files into an array, and get the second one, which avoids having to do any parsing at all:

files=(*)
printf '%s\n' "${files[1]}"

The order in which you get back the files depends on the value of LC_COLLATE. As such, you might want to set LC_COLLATE=C first, if you want a "standard" sorting in all corner cases.

  • Note that array indices start at 1 in sensible shells (zsh, yash, fish, csh, tcsh, rc, es...) and at 0 in ksh and bash. For a solution portable to all Bourne-like shells, you could use: set -- *; printf '%s\n' "$2" instead. – Stéphane Chazelas Feb 22 '16 at 15:36
  • @StéphaneChazelas At least for this question, the tags include "bash", so this answer is specific to that shell. – Chris Down Feb 22 '16 at 18:19
  • ls -C | awk '{ print $1 } looks give same output ... why $2 ? – boctulus Jan 17 at 4:55
7

You would need to add -C as ls uses single-column mode when the output is not a terminal. awk then prints the second column:

ls -C | awk '{print $2}'
2

I think you are looking for

ls -1

It won't show permission, owner, group, date, size... but simple file name in single column.

  • 1
    Not only is this answer wrong, but it's been given before. – Scott Jun 15 at 6:18
  • Although I realize this is wrong for the original question, it is what I was looking for. So, thank you. – AntumDeluge Oct 10 at 0:06
0

The only way works for me is adding "-all". That is:

ls -C -all | awk '{ print $1 }'

Because -all add more columns like user, permissions, etc.

0

As already has been mentioned - using columns for parsing ls output is not very robust because ls breaks the lines according to your file name lengths and terminal width. It often is interesting though to display a single column of a list of elements. You can do this using the cut command:

echo file1 file2 file3 file4 | cut -d" "  -f2

will display

file2

Note that -d allows you to select the column delimiter, so for example with

cur -d, -f2

you can display the second column of a comma separated list.

0

Suppose if you want to display only the particular filename under current path use below command

command:

find path -maxdepth 1 -iname "filename"|sed "s/\.\///g"
0

This is tricky, because parsing ls -C depends on:

  1. filename length, (which itself depends on the specified file list passed to ls -C)
  2. terminal width.
  3. the fact that ls -C output is columnar, but might be configured to varying numbers of spaces as field separators.
  4. the possibility of whitespace in filenames, (the display of which depends upon the particular ls display options chosen).

For now, let's start with the easier problem, (i.e. not #4 above), supposing that there's no whitespace in the filenames. To print column #2, this works:

COLUMNS=$COLUMNS ls -C | tr -s ' ' '\t' | cut -f2

Unrolling that:

  • COLUMNS=$COLUMNS guarantees that the column length fed to | remains consistent with the current terminal display. Changing this to an arbitrary value works too, so COLUMNS=50 or COLUMNS=70 would cause ls -C to rearrange things according to those widths.

    Another method would be to use the -w switch, e.g.:

    ls -w${COLUMNS} -C | tr -s ' ' '\t' | cut -f2
    
  • tr makes the field separators consistent: a single tab between each column.

  • cut outputs the desired column.

  • Whitespace method pending... – agc Jun 15 at 8:09
-1
num_chars=54 # offset
ls -ltr | cut -c$num_chars-

change the number of characters (54) as necessary so you only get the data you want.

  • 2
    to clarify, using 54- tells cut to every character starting at position 54; it doesn't stop at "human-recognized" column – Jeff Schaller May 20 '16 at 16:12
  • It's not a bad idea..just needs to be refined. – prusswan Aug 15 '16 at 10:23

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.