I'm trying to combine arguments to the ls
command to list a directory content. What I'm basically trying to achieve is listing the directory dereferencing all links, but showing explicitly that the item listed is a link. I've tried combining the --dereference
and --classify
options, but instead of showing the link symbol (@
) I get a *
since the link targets an executable file.
Any thoughts on how I can get such result? I'm open to alternatives other than ls
command.
EDIT:
I actually use other options from the ls
command. My current command along with their options is the one bellow:
ls -ogq -LB --group-directories-first --time-style=long-iso
I intend to parse the output inside an application I'm building and can't use the default link output with the arrow (->
). Other items on the directory (e.g. folders and files) must also be listed.
EDIT (2):
Just to clarify, I'm developing a Java apllication that uses a SSH2 API to connect to servers and list directories. The result from the listing is then used to populate a tree using the jsTree jQuery plugin . Currently The command I cited above give's me the following output:
felipe@simba:/mnt/drive$ ls -ogq --group-directories-first --time-style=long-iso
total 12
drwxr-sr-x 2 4096 2014-06-11 18:04 folder1
drwxr-sr-x 6 4096 2014-06-27 19:35 folder2
dr-Sr-s-wt 2 4096 2014-06-27 13:51 folderWithPermissions
-rw-r--r-- 1 0 2014-06-30 10:42 file.txt
lrwxrwxrwx 1 49 2014-06-30 11:36 linkTeste -> folder2/dir/otherfile.txt
By applying a regular expression I can identify what is a folder, file or link by looking at the permissions. But when I have a link I need to list only the link name, instead of name -> destination
. If I use the -L
option for the ls
command only the link name is outputed and I get the referenced destination's permissions (what is a good thing), since the -L
option dereferences the link, but this way I can't know that the link is actually a link.
felipe@simba:/mnt/drive$ ls -ogq -L --group-directories-first --time-style=long-iso
total 12
drwxr-sr-x 2 4096 2014-06-11 18:04 folder1
drwxr-sr-x 6 4096 2014-06-27 19:35 folder2
dr-Sr-s-wt 2 4096 2014-06-27 13:51 folderWithPermissions
-rw-r--r-- 1 0 2014-06-30 10:42 file.txt
-rwxr-xr-x 1 0 2014-06-27 18:40 linkTeste
I need to list only the link name, know it is a link and know what the destination is (file, folder or link). I can handle different kinds of output since I'm going to apply a regular expression anyway.
Alternatives using find
or stat
are also welcome.
Best Answer
Edit in response to updated question
Since you only care about links, directories and regular files, and don't need to deal with the other filetypes that
ls
can identify (FIFOs, sockets etc), you could do something likestat
. For the examples below, I have created the following test environment:As you can see, these include links, links to executables, a file name with a space, one with a tab (
\t
) and one with a newline (\n
). Most of these files would break yourls
approach, butstat
can deal with them correctly:The relevant sections of
man stat
:Note that fields are separated by
\t
, this means you will be able to deal with whitespace within fields (in file names for example) gracefully.You mentioned that you can't deal with
->
. I'm not entirely sure why, but you could either just remove that withsed
or substitute it with another string:
or just parse the file type.
Depending on what you want to do, it might be useful to separate each of the three file types you are searching for and deal with each separately. If so, use
find
1 and its-printf
option:In this case, the
printf
directives areYou could also combine the above into a single command (using
find
's-o
operator) but which lets you use-printf
to print an arbitrary string depending on the file type. For example:The command above will interpret
\t
and\n
correctly if its output is not shown on a terminal. However, to deal with file names with newlines correctly you will need to be careful when parsing (make sure a "line" begins with[file|dir|link]:
) or use\0
as a line terminator in eachprintf
call instead of\n
:1
-maxdepth
and-mindepth
are GNU extensions, so this approach will only work for GNUfind
.The following were posted as solution to the first, less specific version of the question. I am leaving them here since they may be useful to others.
Shell and
readlink
Example output:
The above iterates through all files and directories under the current one and if
readlink
returns successful (if$f
is a link), it will dereference it (readlink -f
, note that this will follow all links. If you only want the first level, remove the-f
) and print the target along with(link)
. If it is not, it will just print$f
.If this is just for you and not intended to be parsed, just use
ls -l
:That will clearly indicate links with
link -> target
.