показывать только исходный файл и целевой связанный файл, используя `ls`

11

Я могу показать целевой файл, на который указывает ссылка ls -l:

snowch$ ls -l /usr/local/bin/mvn
lrwxr-xr-x  1 snowch  admin  29 12 Dec 08:58 /usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn

Есть ли способ показать меньше вывода без необходимости передавать через другую команду, такую ​​как awk? Например:

snowch$ ls ?? /usr/local/bin/mvn
/usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn

Я использую 3.2.53 на OS X 10.9.5. Вывод нескольких команд показан ниже:

snowch$ ls -H /usr/local/bin/mvn
/usr/local/bin/mvn

snowch$ ls -L /usr/local/bin/mvn
/usr/local/bin/mvn

snowch$ file /usr/local/bin/mvn
/usr/local/bin/mvn: POSIX shell script text executable

snowch$ file -b /usr/local/bin/mvn
POSIX shell script text executable
Крис Сноу
источник

Ответы:

7

lsк сожалению, нет возможности извлекать атрибуты файла и отображать их произвольным образом. Некоторые системы имеют отдельные команды для этого (например, GNU имеет statкоманду или функциональность в GNU find).

На большинстве современных систем с большинством файлов это должно работать, хотя:

$ ln -s '/foo/bar -> baz' the-file
$ LC_ALL=C ls -ldn the-file | sed '
   1s/^\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{8\}//'
the-file -> /foo/bar -> baz

Это работает путем удаления первых 8 пустых полей с разделителями в первой строке вывода ls -l. Это должно работать, за исключением систем, где gid не отображается там или первые 2 поля объединяются, когда имеется большое количество ссылок.

С GNU stat:

$ LC_ALL=C stat -c '%N' the-file
'the-file' -> '/foo/bar -> baz'

С GNU find:

$ find the-file -prune \( -type l -printf '%p -> %l\n' -o -printf '%p\n' \)
the-file -> /foo/bar -> baz

С FreeBSD / OS / X stat:

f=the-file
if [ -L "$f" ]; then
  stat -f "%N -> %Y" -- "$f"
else
  printf '%s\n' "$f"
fi

Со zshстатистикой:

zmodload zsh/stat
f=the-file
zstat -LH s -- "$f"
printf '%s\n' ${s[link]:-$f}

У многих систем также есть readlinkкоманда для получения цели ссылки:

f=the-file
if [ -L "$f" ]; then
  printf '%s -> ' "$f"
  readlink -- "$f"
else
  printf '%s\n' "$f"
fi
Стефан Шазелас
источник
stat -f "%N -> %Y" -- /usr/local/bin/mvnработал отлично. Спасибо!
Крис Сноу
1
В старой системе RHEL6 stat имеет GNU coreutils 8.4 и там есть stat -c %N -- /usr/local/bin/mvn. Чтобы удалить цитаты, я должен был | perl -pe 's/['"'"'`]//g'
передать
@cfi tr -d \'\`будет достаточно. Обратите внимание, что эта система RHEL будет иметь GNU, findс которым вы будете иметь больший контроль.
Стефан Шазелас
5

Используйте fileкоманду.

[sreeraj@server ~]$ ls -l mytest
lrwxrwxrwx 1 sreeraj sreeraj 15 Dec 12 09:31 mytest -> /usr/sbin/httpd

[sreeraj@server ~]$ file mytest
mytest: symbolic link to `/usr/sbin/httpd'

или

[sreeraj@server ~]$ file -b mytest
symbolic link to `/usr/sbin/httpd'
[sreeraj@server ~]$

Кроме того , пожалуйста , почитайте через человека страницу lsи проверьте параметры -Lи -Hувидеть , если это будет достаточно ваше требование.

Sree
источник
круто, узнавать что-то новое каждый день.
грабить
@Sree - Большое спасибо! Я пробовал lsварианты, но нет file. К сожалению, ни один из них не работает :(
Крис Сноу,
@SHC Извините, я предположил, что вы на linuxкоробке. Пожалуйста, добавьте в osxкачестве одного из ваших тегов. Это должно привлечь внимание osxпользователей. Я отредактировал пост, чтобы добавить тег, но у меня недостаточно кредитов, чтобы редактирование появилось немедленно.
Сри
@Sree - не беспокойтесь, извините за путаницу. Я все равно проголосовал за ваш ответ, так как он будет полезен, когда я вернусь на Linux-машину.
Крис Сноу,
возможно проверьте утилиту readlink на osx.
tonioc
2

По lsкрайней мере, с GNU (и, по-видимому, tcshреализацией) вы можете взломать $LS_COLORSпеременную окружения, чтобы вставить разделители, где вам нравится (но tcshвстроенная функция ls-Fне делает цели ссылки - только флаги связи ) Обычно lsвставляет произвольные непечатные терминальные экранированные символы. основываясь на значениях, хранящихся в этой среде var, но ничто не мешает нам вставлять что-то еще произвольно. Подробнее об этом здесь .

Например:

LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls ~ -l --color=always | 
sed '\|///|,\|//|!d;//d'

Это помещает строку как //в начало каждого списка (так и непосредственно перед lrwcrwx) и ///\nнепосредственно перед именем файла любой ссылки. sedзатем фильтрует линейные диапазоны - он будет dвыбирать каждую входную строку до тех пор, пока не встретит ее, ///и оттуда через следующую соответствующую строку //удалит соответствующие строки //. Таким образом, он получает только имя ссылки и цель ссылки - независимо от промежуточных символов. Это связано с тем, что /имя файла не может встречаться - и lsпечать по любому пути может произойти только по отдельности.

Увидеть?

mkdir test; cd test
touch 'long


name' shortname
ln -s l* "$(printf %s.ln l*)"; ln -s s* shortname.ln

LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls  -l --color=always | sed '\|///|,\|//|!d;//d'

... который печатает:

long


name.ln -> long


name
shortname.ln -> shortname

Попробуй сам.

mikeserv
источник
Знаете ли вы о какой-либо реализации, кроме современных версий GNU, lsкоторые поддерживают LS_COLORSэтот путь и параметры a --color=alwaysи после аргументов? Если в системе GNU, почему вы используете что-то запутанное, когда вы можете использовать findили stat? Это также, вероятно, не сработает, если вы сделаете это ln -s /// some-file.
Стефан Шазелас
@StephaneChezales - это указывает, по крайней мере, что он должен работать аналогично с BSD ls. Я помню, что читал где-то еще несколько месяцев назад о том, что lsвсе склонны принимать синтаксис типа termcap. Хорошая ln -s ///вещь об этом - но \0NULs работают также - и -Rэурсивно. Что касается того, почему - это легко использовать. В некоторых случаях это проще, чем ... findи здесь, по-видимому, немного больше по теме, чем findбыло бы. В любом случае, не так много людей считают это, поэтому я упоминаю об этом, когда мне напоминают.
mikeserv
Смотрите страницу руководства или там для FreeBSD. Если вы хотите что-то тестировать во FreeBSD, вы можете использовать живые компакт-диски, такие как GhostBSD / mfsbsd, в виртуальной машине.
Стефан Шазелас
@ StéphaneChazelas - нет, мне не нужно это проверять - совершенно другое животное . Если вы хотите посмотреть, источник GNU также связан в ссылке в этом ответе. Интересно, где я прочитал эту другую вещь? большое спасибо за указание на это, хотя, это было ошибочное предположение, что я счастлив отказаться. я отредактировал ответ.
mikeserv
последние версии tcshимеют ls-Fвстроенную функцию, которая поддерживает LS_COLORSтот же способ, что и некоторые версии GNU ls, но прибегает к вызову, ls -Fесли вы передаете ему какую-либо опцию, так что это не будет работать, если только lsGNU не установлен lsв вашей системе.
Стефан Шазелас
-1

[В Linux / Bash]

Я бы сделал это:

ls -l | sed -e"s/ \+/ /g" | cut -d' ' -f 9-

Команда sedсворачивает несколько пробелов в один пробел; cutизвлекает 9th поле и далее , где поле сепаратор представляет собой пространство.

Типичный вывод из этого:

libboost_atomic.a
libboost_atomic.so -> libboost_atomic.so.1.57.0
libboost_atomic.so.1.57.0
...
libboost_wserialization.a
libboost_wserialization.so -> libboost_wserialization.so.1.57.0
libboost_wserialization.so.1.57.0

Альтернативы:

ls -l | awk '{ print $9, $10, $11 }'
ls -l | awk '{ $1 = $2 = $3 = $4 = $5 = $6 = $7 = $8 = "" ; print }'

Но они несовершенны: первый может выводить конечные пробелы; второе, ведущие пробелы.

Rhubbarb
источник
В вопросе прямо говорилось: «... без необходимости передавать через другую команду ...»
Джефф Шаллер
@JeffSchaller: Хороший вопрос; Я согласен. Я надеюсь, однако, что это все еще полезно для кого-то, кто хочет получить ответ на заглавный вопрос (без подробностей в описании).
Rhubbarb