ls
이제 프로그램 을 두 개의 파일로 분할했습니다 . awk
의 유일한 목적 은 . 다음과 같이 보입니다:ls -lhF
my_ls.sh
my_ls.awk
my_ls.sh
ls -lhF
my_ls.awk
#!/bin/bash
ls -lhF "$@" | my_ls.awk
ls -lhF
awk 스크립트 자체를 통해 출력을 읽을 수 있는 방법이 있는지 궁금합니다.
편집하다:나의 주요 목적은 현재 디렉터리 내용을 멋진 트리 형태로 표시하는 스크립트를 작성하는 것입니다. 초안 버전은 my_ls.awk
다음과 같습니다.
#!/usr/bin/awk -f
( NF >= 9 ) {
print "|-- [" $5 "] " $9
}
이것이것이 내가 지금까지 달성한 것입니다.
답변1
출력을 구문 분석해서는 안 된다는 다른 제안을 추가할 것이므로 ls
이는 나쁜 예입니다. 하지만 좀 더 일반적인 질문으로 awk 스크립트를 매개변수로 awk
.
#!/bin/bash
ls -lhF "$@" | awk '
( NF >= 9 ) {
print "|-- [" $5 "] " $9
}'
awk 스크립트에 '
(작은 따옴표) 문자가 포함되어야 하는 경우 따옴표로 묶어야 합니다. '\''
(닫는 작은 따옴표, 리터럴 작은 따옴표, 여는 작은 따옴표)를 사용하십시오.
인용을 피하려면 다음을 사용할 수 있습니다.여기 문서대신에. 그러나 표준 입력을 사용하여 awk와 스크립트 모두에 입력을 제공할 수 없기 때문에 이는 어색합니다. 추가 파일 설명자를 사용해야 합니다(참조:추가 파일 설명자는 언제 사용됩니까? 파일 설명자 및 쉘 스크립트).
#!/bin/bash
ls -lhF "$@" | awk -f /dev/fd/3 3<<'EOF'
( NF >= 9 ) {
print "|-- [" $5 "] " $9
}
EOF
awk에서는 getline
함수와 파이프 구성을 사용하여 다른 명령의 입력을 읽을 수 있습니다. 이것은 awk의 기본 목적이 아니지만 작동하도록 만들 수 있습니다. 오류가 발생하기 쉬운 기본 쉘의 파일 이름 인수를 인용해야 합니다. 처리 중인 텍스트가 예상 소스(표준 입력 또는 명령줄에 이름이 지정된 파일)에서 나오지 않으므로 결국 블록의 모든 코드가 생성됩니다 BEGIN
.
#!/usr/bin/awk -f
BEGIN {
command = "ls -lhF"
for (i = 1; i <= ARGC; i++) {
arg = ARGV[i];
gsub("'", "'\\''", arg);
command = command " '" arg "'";
}
ARGC = 0; for (i in ARGV) delete ARGV[i];
while ((command | getline) > 0) {
if (NF >= 9) { print "|-- [" $5 "] " $9 }
}
}
간단히 말해서, 쉘이 잘하는 작업(예: 명령을 함께 연결하는 것)에는 쉘을 사용하고, 잘하는 작업(예: 텍스트 처리)에는 awk를 사용하십시오.
답변2
무엇을 하려는지 잘 모르겠지만 발생할 수 있는 한 가지 문제는 마지막 필드로 간주되지만 기본 구문 분석에서는 그렇게 간주되지 않는 항목을 awk
인쇄하는 것 입니다. 예를 들어. ls
awk
-rw-r--r-- | 433k | filename-with-no-spaces
-rw-r--r-- | 1k | link containing spaces -> /home/user/filename-with-no-spaces
어떻게든 마지막 필드를 분리해야 합니다 ls
. 아래에서 취한 접근 방식은 모든 이전 필드와 구분 기호의 길이를 찾는 것입니다. 나머지는 파일 이름 필드(링크 대상과 같은 기타 정보 포함)입니다.
아래 스크립트는 가변 너비의 최대 너비를 결정합니다.크기필드(출력 형식에 필요) 예를 들어 이 너비를 얻는 방법은 다양합니다.(1)awk
각 출력 라인을 처리 하려면 ls
메인 루프에서 후속 처리를 위해 각 라인을 배열에 추가합니다 END{ }
. 또는(2) 출력을 ls
임시 파일에 쓴 다음 awk
파일을 처리합니다. 아래 표시된 방법을 사용하십시오.(2).
ls
의 경우처럼 의 출력은 예상치 못한 사소한 출력을 원하는 방식으로 보낼 수 있으므로 일반적으로 구문 분석 요구 사항에 더 적합하도록 출력을 사용하고 사용자 정의하는 것이 더 안전합니다 link
.find
f=7 # the number of (multi-space) delimiters before the start of the filename
myls="$(mktemp)" # a temp file to hold output from `ls`
w=$(ls --color=always -lFHk ~/ |tee "$myls" |awk '{print $5}' |wc -L) # max width of size field
h=k # size unit
awk --re-interval -v"f=$f" -v"w=$w" -v"h=$h" '
NF >= f {
regex = "^([^ ]+ +){"f"}"
match( $0, regex ) # find start of name field
printf( "%s | %"w"s%s | %s\n", $1, $5, h, substr( $0, RLENGTH ))
}' "$myls"
rm "$myls"
답변3
tree
휠을 재발명하는 것을 피하고 대신 디렉토리의 파일/폴더 및 하위 디렉토리 파일/폴더를 표시하는 를 사용하는 것이 좋습니다 .
tree(1) - Linux 매뉴얼 페이지
이름
트리 - 디렉터리 내용을 트리 형식으로 나열합니다.
요약
tree[-adfghilnopqrstuvxACDFNS] [-L 레벨[-R]] [-H baseHREF] [-T 제목] [-o 파일 이름] [--nolinks] [-P 모드] [-I 모드] [--inodes] [ --device] [--noreport] [--dirsfirst] [--version] [--help] [--filelimit #] [디렉토리...]
설명하다
Tree는 깊게 들여쓰기된 파일 목록을 생성하는 재귀적 디렉터리 목록 프로그램입니다. LS_COLORS 환경 변수가 설정되고 출력이 tty로 이루어지며 -C 플래그가 사용되는 경우 색상 ala dircolors가 지원됩니다. 인수가 없으면 tree는 현재 디렉터리의 파일을 나열합니다. 디렉토리 인수가 주어지면 트리는 주어진 디렉토리에서 발견된 모든 파일 및/또는 디렉토리를 순차적으로 나열합니다. 발견된 모든 파일/디렉터리 나열이 완료되면 트리는 나열된 파일 및/또는 디렉터리의 총 수를 반환합니다.
기본적으로 기호 링크가 발견되면 기호 링크에서 참조하는 경로가 다음 형식으로 링크 이름 뒤에 인쇄됩니다.
이름->실제 경로
"-l" 옵션이 지정되고 심볼릭 링크가 실제 디렉터리를 참조하는 경우 트리는 마치 실제 디렉터리인 것처럼 심볼릭 링크의 경로를 따릅니다.