명령 출력을 매개변수 목록으로 스크립트에 어떻게 전달할 수 있나요?

명령 출력을 매개변수 목록으로 스크립트에 어떻게 전달할 수 있나요?

현재 디렉터리에 있는 모든 파일의 시작 부분에 콘텐츠를 추가하고 싶습니다. 현재 작업 디렉터리에서 모든 파일 이름을 한 번에 가져와 인수로 전달하는 방법을 배워야 합니다. 각 파일을 스크립트에 대한 인수로 수동으로 지정하여 이 작업을 수행할 필요가 없습니다. 나는 이 새로운 지식을 추가 스크립트에 사용하고 싶습니다. 나는 측면이나 다른 솔루션이 필요하지 않습니다. command( ls) 출력을 가져와 매개변수로 전달하는 방법을 배워야 합니다 . 나는 이것을 시도했지만 실패했습니다.

./file-edit.sh $(ls)
./file-edit.sh `ls`

이것은 내 작업 스크립트입니다.

#!/bin/bash
lineno=2            # Append from line 2 
BAD_ARGS=85         # Error code

string0="###################################################################"
string2="#Description    :"
string3="#Date           :`date +%d-%B-%Y`"
string4="#Author         :Milos Stojanovic"
string5="#Contact:       :https://www.linkedin.com/in/xxx/"
string6="###################################################################"
# Can be any other strings

if [ ! -f $1 ]; then
        echo "Please specify at least 1 filename as an argument!"
        exit $BAD_ARGS
fi

until [ -z  "$1" ]
do
        string1="#Script Name    :$1"
        file=$1;
        sed -i ""$lineno"i $string0\n$string1\n$string2\n$string3\n$string4\n$string5\n$string6" $file
        echo "File "\'$file\'" altered at line number: $lineno"
        shift 1
done

exit 0

답변1

스크립트에서 각 매개변수를 개별적으로 처리하려면 다음과 같이 스크립트에서 루프를 사용하세요.

for pathname do

    # Insert code here that uses "$pathname".
    # You will not need to shift arguments.

done

현재 디렉토리의 모든 이름으로 스크립트를 호출하려면 다음을 사용하십시오.

./script.sh ./*

쉘은 ./*패턴을 현재 디렉토리의 모든 이름을 포함하는 목록으로 확장합니다.

사용에 비해 장점은 유효한 문자(공백, 탭 및 줄바꿈 포함)가 포함된 파일 이름을 ls사용하지 않으므로 처리할 수 있다는 것 입니다.ls

또는 파일 이름 와일드카드를 스크립트 자체로 이동할 수 있습니다(명령줄에서 스크립트에 인수를 제공하지 않아도 됨).

for pathname in ./*; do
    # Insert code here that uses "$pathname".
done

스크립트가 일반 파일을 참조하는 이름과 비전통적인 파일(예: 디렉터리)을 참조하는 이름을 구별해야 하는 경우 -f루프에서 테스트를 사용하세요.

# skip non-regular files
[ ! -f "$pathname" ] && continue

이는 여전히 일반 파일에 대한 심볼릭 링크를 허용합니다. 이것도 건너뛰려면 테스트를 다음으로 변경하세요.

if [ ! -f "$pathname" ] || [ -L "$pathname" ]; then
    # Skip non-regular files and symbolic links.
    continue
fi

기타 제안사항:

문자열에 개행 문자를 포함하여 여러 줄 문자열을 변수에 할당할 수 있습니다.

boilerplate='Hello and welcome!
This is my program.
Enjoy'

텍스트 문서의 두 번째 줄 뒤에 텍스트를 삽입하려면 sed( -i여기서는 내부 편집에 사용됨)을 사용합니다.

printf '%s\n' "$boilerplate" | sed -i '2r /dev/stdin' somefile

또는 여기 문서를 사용하여

sed -i '2r /dev/stdin' somefile <<END_BOILERPLATE
Hello and welcome!
This is my program.
Enjoy
END_BOILERPLATE

답변2

다른 답변은 정확히 무엇을 잘못하고 있는지 다루지 않기 때문에

나는 이것을 시도했지만 실패했습니다.

./file-edit.sh $(ls)

귀하의 스크립트를 시험해 본 결과 다음과 같은 결과를 얻었습니다.

$ ./file-edit.sh $(ls)
Please specify at least 1 filename as an argument!

출력을 검사할 때 ls디렉터리가 먼저 나열되는 것을 확인했습니다. 하위 디렉터리가 없는 디렉터리로 이동하면 다음과 같은 결과가 나타납니다.

$ ./file-edit.sh $(ls)
File 'a' altered at line number: 2
File 'b' altered at line number: 2
File 'c' altered at line number: 2 

따라서 주장을 확인하는 방식이 문제입니다. -f일반 파일에서만 성공합니다. 첫 번째 인수에 대해 디렉토리가 제공되었음을 확인하고 사용자가 파일 이름 인수를 제공했음에도 불구하고 제공하지 않았다는 오류를 표시합니다.

최소한 하나의 인수가 제공되었는지 확인하려면 $#이를 사용하여 제공된 인수 수만큼 확장하세요.

if [ "$#" -eq 0 ]; then
  echo "Please specify at least 1 filename as an argument!"
  ...

일반 파일인지 확인하려면 루프에서 수행하고 첫 번째 파일뿐만 아니라 각 파일을 확인하십시오.

until [ -z  "$1" ]
do
        string1="#Script Name    :$1"
        file=$1;
        if [ -f "$file" ]; then
                sed -i "${lineno}i $string0\n$string1\n$string2\n$string3\n$string4\n$string5\n$string6" "$file"
                echo "File '$file' altered at line number: $lineno"
        fi
        shift 1
done

이제 이 코드는 비전통적인 파일 매개변수를 무시하려는 경우를 위한 것이지만 원하는 경우 비전통적인 파일이 보일 때 종료되도록 쉽게 변경할 수 있습니다.

하지만 ls그러한 출력을 사용하는 것은 권장되지 않습니다. 파일 이름에 공백이 있을 수 있습니다. bash는 모든 것을 공백으로 분할합니다. 파일이 있는 경우 foo bar.txtbash는 파일을 분할하고 스크립트는 파일 foobar.txt.

귀하의 질문에 대한 의견을 보면 누군가가 대신 glob을 사용하도록 제안한 것 같습니다. 나는 그것이 작동하지 않는다는 당신의 요점을 잘 이해하지 못합니다. ./file-edit.sh *나에게 잘 작동합니다.

답변3

나는 다음과 같은 것을 선택할 것입니다 :

find <dir> -type f -print0 | xargs -0 sed -i '...'

전체주기보다는 until. 그것도 더 빨라야 합니다.

대안을 게시하는 이유:

  • ls출력을 구문 분석하면 안 됩니다.(600+투표)

  • 나는 내 스크립트에서 한 줄 빠른 작업을 수행하기 위해 내 자신의(아마도 버그가 있는) 여러 줄 루프 구성을 해킹하는 것보다 오히려 시스템 메커니즘을 사용하고 싶습니다.

  • 대부분의 자체 구축 구조에는 "공백이 있는 파일" 문제가 발생하거나 매개변수 길이 문제가 있습니다.

관련 정보