LS 명령을 사용하여 디렉터리를 나열할 때 파일 형식 및 역참조

LS 명령을 사용하여 디렉터리를 나열할 때 파일 형식 및 역참조

ls디렉토리의 내용을 나열하기 위해 명령의 매개변수를 결합 하려고 합니다 . 내가 기본적으로 달성하려고 하는 것은 모든 링크를 역참조하는 디렉토리를 나열하지만 나열된 항목이 링크임을 명확하게 표시하는 것입니다. --dereference및 옵션을 결합하려고 시도했지만 링크 대상이 실행 파일이기 때문에 --classify링크 기호( ) 대신 이 표시 @되었습니다 .*

어떻게 이런 결과를 얻을 수 있는지에 대한 아이디어가 있나요? ls명령 이외의 옵션도 열려 있습니다 .

편집하다: 실제로 명령에서 다른 옵션을 사용했습니다 ls. 내 현재 명령과 해당 옵션은 다음과 같습니다.

ls -ogq -LB --group-directories-first --time-style=long-iso

->구축 중인 애플리케이션 내에서 출력을 구문 분석하려고 하는데 화살표( )가 있는 기본 링크 출력을 사용할 수 없습니다 . 폴더, 파일 등 디렉터리의 다른 항목도 나열되어야 합니다.

편집(2):

명확히 하기 위해 SSH2 API를 사용하여 서버에 연결하고 디렉터리를 나열하는 Java 애플리케이션을 개발 중입니다. 그런 다음 목록의 결과는 jsTree jQuery 플러그인을 사용하여 트리를 채우는 데 사용됩니다. 현재 위에서 인용한 명령은 다음과 같은 출력을 제공합니다.

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

정규식을 적용하면 권한을 확인하여 폴더, 파일 또는 링크가 무엇인지 식별할 수 있습니다. 하지만 링크가 있는 경우 대신 링크 이름만 나열하면 됩니다 . 명령의 옵션을 name -> destination사용하면 링크 이름만 출력되고 참조된 대상의 권한을 얻게 됩니다(좋은 점입니다). 옵션 의 링크 참조를 해제했지만 링크가 실제로 연결인지 알 수 있는 방법이 없습니다.-Lls-L

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

링크 이름을 나열하고 그것이 링크인지, 대상이 무엇인지(파일, 폴더 또는 링크)를 알아야 합니다. 어쨌든 정규식을 적용하므로 다양한 유형의 출력을 처리할 수 있습니다.

find또는 를 사용하는 대안 도 환영합니다 .stat

답변1

업데이트된 질문에 대한 응답으로 편집됨

링크, 디렉터리 및 일반 파일에만 관심이 있고 ls인식되는 다른 파일 형식(FIFO, 소켓 등) 을 처리할 필요가 없으므로 stat아래 예에서는 . 다음 테스트 환경:

$ ls -l
total 4.0K
-rw-r--r-- 1 terdon terdon    0 Jun 30 23:12 a new?line 
-rw-r--r-- 1 terdon terdon    0 Jun 30 23:12 a space
-rw-r--r-- 1 terdon terdon    0 Jun 30 23:12 a?tab
drwxr-xr-x 2 terdon terdon 4.0K Jun 30 23:11 dir1
lrwxrwxrwx 1 terdon terdon    4 Jun 30 23:13 linktodir1 -> dir1
lrwxrwxrwx 1 terdon terdon    7 Jun 30 23:13 sh -> /bin/sh

보시다시피 여기에는 링크, 실행 파일에 대한 링크, 공백이 있는 파일 이름, 탭이 있는 파일 이름( ), \t줄바꿈( )이 있는 \n파일 이름이 포함됩니다. 이러한 파일의 대부분은 ls메서드를 손상시키지만 stat올바르게 처리할 수 있습니다.

$ stat --printf "%A\t%N\t%F\n" * 
-rw-r--r--  ‘a new\nline’   regular file
-rw-r--r--  ‘a space’   regular file
-rw-r--r--  ‘a\ttab’    regular file
drwxr-xr-x  ‘dir1’  directory
lrwxrwxrwx  ‘linktodir1’ -> ‘dir1’  symbolic link
lrwxrwxrwx  ‘sh’ -> ‘/bin/sh’   symbolic link

관련 부품 man stat:

--printf=형식

--format과 비슷하지만 백슬래시 이스케이프가 해석되고 강제로 후행 줄 바꿈이 출력되지 않습니다. 개행 문자를 원하면 FORMAT에 \n을 포함하세요.

%사람이 읽을 수 있는 액세스 권한 형식

%F 파일 형식

%N 인용된 파일 이름, 심볼릭 링크인 경우 인용되지 않음

필드는 구분되어 있으므로 \t필드의 공백(예: 파일 이름의 공백)을 적절하게 처리할 수 있습니다.

당신은 대처할 수 없다고 언급했습니다 ->. 왜 그런지는 잘 모르겠지만 사용할 수 있습니다.sed

$ stat --printf "%A\t%N\t%F\n" * | sed 's/->//' 
lrwxrwxrwx  ‘linktodir1’  ‘dir1’    symbolic link

아니면 다른 문자열로 바꾸세요:

$ stat --printf "%A\t%N\t%F\n" * | sed 's/->/→/' | grep linktodir
lrwxrwxrwx  ‘linktodir1’ → ‘dir1’   symbolic link

아니면 파일 형식을 구문 분석하면 됩니다.


수행하려는 작업에 따라 검색 중인 세 가지 파일 형식을 분리하여 개별적으로 처리하는 것이 유용할 수 있습니다. 그렇다면 find1 과 해당 -printf옵션을 사용하십시오.

$ find ./ -maxdepth 1 -mindepth 1 -type f -printf '%M\t%P\t%l\n'  ## files
$ find ./ -maxdepth 1 -mindepth 1 -type d -printf '%M\t%P\t%l\n'  ## directories
$ find ./ -maxdepth 1 -mindepth 1 -type l -printf '%M\t%P\t%l\n'  ## links

이 경우 printf지시사항은 다음과 같습니다.

          %M     File's permissions (in symbolic form, as for  ls).   This
                 directive is supported in findutils 4.2.5 and later.
          %P     File's  name  with  the name of the command line argument
                 under which it was found removed.
          %l     Object of symbolic link (empty string if file  is  not  a
                 symbolic link).

위의 명령을 단일 명령으로 결합할 수도 있지만( find' 연산자 사용), 파일 유형에 따라 임의의 문자열을 인쇄할 -o수 있습니다 . -printf예를 들어:

$ find ./ -maxdepth 1 -mindepth 1 \( -type l -printf 'link:\t%M\t%P\t%l\n' \) \
-o \( -type d -printf 'dir:\t%M\t%P\n' \) \
-o \( -type f -printf 'file:\t%M\t%P\n' \) 
file:   -rw-r--r--  a?tab
file:   -rw-r--r--  a space
link:   lrwxrwxrwx  linktodir1  dir1
file:   -rw-r--r--  a new?line
dir:    drwxr-xr-x  dir1
link:   lrwxrwxrwx  sh  /bin/sh

위 명령의 출력이 터미널에 표시되지 않으면 명령이 올바르게 해석됩니다 \t. \n그러나 개행 문자가 포함된 파일 이름을 적절하게 처리하려면 구문 분석할 때 주의하거나("line"이 로 시작하는지 확인 [file|dir|link]:) 대신 \0각 호출에서 줄 종결자로 사용해야 합니다 .printf\n

$ find ./ -maxdepth 1 -mindepth 1 \( -type l -printf 'link:\t%M\t%P\t%l\0' \) \
-o \( -type d -printf 'dir:\t%M\t%P\0' \) \
-o \( -type f -printf 'file:\t%M\t%P\0' \)

1 -maxdepth 이고 -mindepthGNU 확장이므로 이 방법은 GNU에서만 작동합니다 find.


다음은 문제의 덜 구체적인 첫 번째 버전에 대한 솔루션으로 게시되었습니다. 다른 사람들에게 유용할 수 있기 때문에 여기에 남겨 두겠습니다.

  1. 쉘과readlink

    for f in *; do 
     readlink "$f" >/dev/null && echo "$(readlink -f "$f") (link)" || echo "$f";
    done
    

    출력 예:

    /etc (link)
    foo
    sample.R
    sample.R~
    

    위의 루프는 현재 파일 및 디렉터리 아래의 모든 파일 및 디렉터리를 반복하고 성공을 반환하면 ( 링크의 readlink경우 ) 이를 역참조합니다( , 다음 내용에 유의하세요.$freadlink -f모두링크. 첫 번째 레벨만 필요한 경우 이를 제거 -f하고 해당 레벨로 대상을 인쇄하십시오 (link). 그렇지 않은 경우에는 그냥 인쇄됩니다 $f.

  2. 이것이 귀하만을 위한 것이며 구문 분석할 의도가 없는 경우 다음을 사용하십시오 ls -l.

    $ ls -l
    total 512116
    -rw-r--r-- 1 terdon terdon    100641 Jun 30 19:10 er
    lrwxrwxrwx 1 terdon terdon         5 Jun 30 19:12 etc -> /etc/
    -rw-r--r-- 1 terdon terdon 524288000 Jun 30 19:10 foo
    -rwxr--r-- 1 terdon terdon       353 Jun 30 15:22 sample.R
    -rwxr--r-- 1 terdon terdon       249 Jun 30 14:51 sample.R~
    

    그러면 와의 링크가 명확하게 표시됩니다 link -> target.

관련 정보