0

There is a directory that contains only symbolic link files.

I'd like to pipe over the ls command from this directory and give it as a factor for the readlink command to print out the original file

I tried the command below, but I couldn't find the answer

$ ls opt/integrity/ | xargs readlink 

Does anyone know the appropriate command to output the original file via ls and readlink commands for all files that exist in the directory

2
  • roaima already says that in his answer, but: Why not to parse ls output (and what to do instead) Commented Apr 5, 2023 at 7:05
  • "I tried the command below, but I couldn't find the answer" - What happened? What didn't work for you? We can't look over your shoulder so you have to tell us (in your question) Commented Apr 5, 2023 at 7:14

2 Answers 2

1

If you mean that you want to list symlinks along with the target paths they point to, with zsh:

$ zmodload zsh/stat $ stat -n +link /dev/*(@) /dev/cdrom sr0 /dev/core /proc/kcore /dev/fd /proc/self/fd /dev/initctl /run/initctl /dev/log /run/systemd/journal/dev-log /dev/rtc rtc0 /dev/stderr /proc/self/fd/2 /dev/stdin /proc/self/fd/0 /dev/stdout /proc/self/fd/1 

With the ast-open implementation of ls, you can also do:

$ ls -d --format='%(name)s %(linkpath)s' /dev/*(@) /dev/cdrom sr0 /dev/core /proc/kcore /dev/fd /dev/initctl /run/initctl /dev/log /run/systemd/journal/dev-log /dev/rtc rtc0 /dev/stderr /proc/self/fd/2 /dev/stdin /proc/self/fd/0 /dev/stdout /proc/self/fd/1 

With GNU find:

$ find /dev/ -maxdepth 1 -type l -printf '%p %l\n' /dev/cdrom sr0 /dev/rtc rtc0 /dev/log /run/systemd/journal/dev-log /dev/initctl /run/initctl /dev/core /proc/kcore /dev/stderr /proc/self/fd/2 /dev/stdout /proc/self/fd/1 /dev/stdin /proc/self/fd/0 /dev/fd /proc/self/fd 

(unsorted and includes hidden files if any).

With GNU stat:

$ command stat -c %N /dev/*(@) '/dev/cdrom' -> 'sr0' '/dev/core' -> '/proc/kcore' '/dev/fd' -> '/proc/self/fd' '/dev/initctl' -> '/run/initctl' '/dev/log' -> '/run/systemd/journal/dev-log' '/dev/rtc' -> 'rtc0' '/dev/stderr' -> '/proc/self/fd/2' '/dev/stdin' -> '/proc/self/fd/0' '/dev/stdout' -> '/proc/self/fd/1' 

path/to/*(@) expands to the non-hidden files of type symlink in the path/to directory, using the @ glob qualifier. That feature is zsh-specific. In other shells you generally need to resort to find to select files based on their type.

For instance, in bash 4.4+, and on GNU systems, the equivalent of expanding /dev/*(@) would be something like:

readarray -td '' files < <( LC_ALL=C find /dev/ -mindepth 1 -maxdepth 1 ! -name '.*' -type l -print0 | sort -z ) if (( ${#files[@]} )); then stat -c %N -- "${files[@]}" else echo>&2 No match. fi 
1

There is absolutely no need to use ls to list the files for readlink (it's intended to provide a convenient listing of files for people not for machines). Instead you can have the shell expand * to match all files in the directory

readlink opt/integrity/* 

Your original command would have probably worked, provided that the path opt/integrity existed and none of the source filenames contained spaces (or other "special" characters). But a wildcard handles this already so is a safer solution.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.