ls 텍스트 출력을 조작하여 파일 이름 경로 추가

ls 텍스트 출력을 조작하여 파일 이름 경로 추가

때때로 다음과 같은 ls 출력 형식의 파일을 얻습니다.

/etc/cron.d:
-rw-r--r-- 1 root root 128 May 15  2020 0hourly
-rw------- 1 root root 235 Dec 17  2020 sysstat
/etc/cron.daily:
-rw------- 1 root root 235 Dec 17  2020 sysstat

일반 Gnu 도구를 사용하거나 bash 내부를 삭제하여 이를 조작할 수 있는 기회가 있습니까?

-rw-r--r-- 1 root root 128 May 15  2020 /etc/cron.d/0hourly
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.d/sysstat
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.daily/sysstat

훌륭해요.

가장 쉬운 방법은 다음과 같이 파일 경로를 제거하는 것입니다. cat <filename> | grep -v -E "^\/[a-z]"

하지만 제가 말했듯이 이 경로를 파일 이름이 있는 후속 줄로 어떻게 이동할 수 있습니까?

주어진 명령은 다음과 같습니다: ls -lR /etc/cron* > <filename>.

나는 해당 출력에 영향을 미치지 않지만 ls에 의해 실행된 이러한 명령의 출력을 <filename>나에게 전송되는 별도의 파일로 리디렉션합니다.

내가 하고 싶은 것은 그 내용을 언급된 두 번째 결과로 조작하는 것입니다. 기본적으로 첫 번째 줄을 가져와서 파일의 2번째와 3번째 줄에 경로를 적용한 다음, 4번째 줄을 가져와 5번째 줄에 적용합니다. 그런 다음 이를 일반 방법으로 구성합니다.

awk를 사용하면 효과가 있을 것 같아요.

답변1

파일 이름이나 디렉터리 이름에 공백이 없으면 POSIX awk를 사용하여 다음을 수행할 수 있습니다.

$ awk '
    NF==1 && sub(/:$/,"/") { dir=$0; next }
    match($0,/[^[:space:]]+$/) { $0=substr($0,1,RSTART-1) dir substr($0,RSTART) }
    { print }
' file
-rw-r--r-- 1 root root 128 May 15  2020 /etc/cron.d/0hourly
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.d/sysstat
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.daily/sysstat

또는 파일/디렉터리 이름에 공백이 포함될 수 있지만 디렉터리 경로가 항상 다음으로 시작 /하고 ls출력에 항상 파일 이름 앞에 정확히 동일한 수의 필드가 있는 경우(예제에서와 같이) 다음을 수행할 수 있습니다.

$ awk '
    /^\// && sub(/:$/,"/") { dir=$0; next }
    match($0,/^([^[:space:]]+[[:space:]]+){8}/) { $0=substr($0,1,RLENGTH) dir substr($0,RLENGTH+1) }
    { print }
' file

그러나 ls이러한 필드를 사용하여 출력을 생성하는 것이 항상 가능한 것은 아니며( ls날짜/시간 출력은 파일의 수명과 로캘에 따라 다르며 예를 들어 사용자 ID에는 공백이 포함될 수 있음) 각 파일 줄의 모든 문자가 나타날 수 있습니다. 파일 및 디렉터리 이름에는 :YMMV를 제외한 모든 문자가 포함될 수 있으므로 디렉터리 이름은 사용자가 생각하는 /대로 끝날 수 있습니다. NUL줄을 구별한 다음 각 파일 줄에서 파일 이름을 찾아보세요. 또한 파일 이름에 개행 문자가 포함될 수 있는데 이는 완전히 또 다른 문제입니다.

ls따라서 생성할 수 있는 모든 가능한 출력을 구문 분석하는 신뢰할 수 있는 방법은 없습니다 . 이 작업을 수행하려면 호출하는 컨텍스트에 관계없이 충분하다고 생각하거나 원하는 패턴 일치가 무엇인지 파악한 ls다음 이를 기반으로 스크립트를 작성하면 됩니다.

일부 다른 도구는 ls구문 분석해야 하는 출력 파일을 생성하므로 구문 분석을 시도하면 안 된다는 것을 우리 모두 알고 있으므로 다른 도구를 수정해야 합니다 ls(참조http://mywiki.wooledge.org/ParsingLs그리고왜 `ls`를 구문 분석하지 *않나요*(그리고 어떻게 수행합니까)?) 따라서 이 도구는 실패할 것입니다.

답변2

사용 중인 명령이나 이 출력이 나타나는 이유를 표시하지 않았지만 목표가 일치하는 모든 파일과 디렉터리를 나열하는 것이라면 /etc/cron*대신 다음을 사용할 수 있습니다 find.

find /etc/cron*

또는 전체 목록을 원하는 경우(GNU find):

find /etc/cron* -ls

어느 find:

find /etc/cron* -exec ls -ld {} +

내 Arch Linux의 샘플 출력은 다음과 같습니다.

$ ls /etc/cron*
/etc/cron.deny  /etc/crontab  /etc/crontab~  /etc/crontab.pacnew

/etc/cron.d:
0hourly

/etc/cron.daily:

/etc/cron.hourly:
0anacron

/etc/cron.monthly:

/etc/cron.weekly:

그리고 find:

$ find /etc/cron* -ls
   262172      4 drwxr-xr-x   2 root     root         4096 Jan 23 19:41 /etc/cron.d
   263666      4 -rw-r--r--   1 root     root          128 Jan 14 14:59 /etc/cron.d/0hourly
   262173      4 drwxr-xr-x   2 root     root         4096 Sep 30 11:38 /etc/cron.daily
   262618      4 -rw-r--r--   1 root     root           74 Jan 14 14:59 /etc/cron.deny
   262174      4 drwxr-xr-x   2 root     root         4096 Jan 23 19:41 /etc/cron.hourly
   263665      4 -rwxr-xr-x   1 root     root          843 Jan 14 14:59 /etc/cron.hourly/0anacron
   262175      4 drwxr-xr-x   2 root     root         4096 Jun 30  2016 /etc/cron.monthly
   262632      0 -rw-r--r--   1 root     root            0 Oct 31  2017 /etc/crontab
   262633      4 -rw-r--r--   1 root     root           49 Sep 22  2017 /etc/crontab~
   272465      4 -rw-r--r--   1 root     root          119 Jan 14 14:59 /etc/crontab.pacnew
   262176      4 drwxr-xr-x   2 root     root         4096 Sep 30 11:38 /etc/cron.weekly
   275802      4 -rwxr--r--   1 root     root           68 Sep 30 11:37 /etc/cron.weekly/clamscan.sh

답변3

솔루션TXR 불분명한 음성.

ls이 출력을 어딘가에서 얻었고 이를 사용해야 한다는 사실을 당연하게 여기십시오 . 원래의 시간과 기계로 돌아가서 다른 형식으로 정보를 얻을 수는 없습니다.

$ txr lsdata.tl < lsdata
-rw-r--r-- 1 root root 128 May 15  2020 /etc/cron.d/0hourly
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.d/sysstat
-rw------- 1 root root 235 Dec 17  2020 /etc/cron.daily/sysstat

어디 lsdata.tl:

(let ((curdir ""))
  (whilet ((line (get-line)))
    (match-case line
      (`@dir:` (set curdir dir))
      (`@{metadata 39} @name` (put-line `@metadata @curdir/@name`)))))

완벽하지는 않습니다. 로 끝나는 이름으로 속일 수 있습니다 :. 디렉토리 라인 영역이 항상 절대 경로라고 가정할 수 있다면 이를 일치 항목에 포함할 수 있습니다.

(let ((curdir ""))
  (whilet ((line (get-line)))
    (match-case line
      (`/@dir:` (set curdir dir))
      (`@{metadata 39} @name` (put-line `@metadata /@curdir/@name`)))))

답변4

원하는 것이 무엇인지 확실하지 않지만 다음 명령을 시도해 보십시오.

$ ls -la | awk -v path=$PWD '{$NF=path"\/"$NF;print}' |sed 's| /| \t/|g'

경로 정렬에 관심이 없다면 sed 부분을 제거할 수 있습니다.

관련 정보