programing

파일의 각 줄에 대해 egchmod 명령을 어떻게 실행합니까?

stoneblock 2023. 4. 29. 08:14

파일의 각 줄에 대해 egchmod 명령을 어떻게 실행합니까?

예를 들어, 현재 다음을 사용하여 UNIX 경로를 파일로 작성한 파일 몇 개를 변경하고 있습니다.

cat file.txt | while read in; do chmod 755 "$in"; done

더 우아하고 안전한 방법이 있을까요?

파일을 한 줄씩 읽고 명령 실행: 4개 이상의 답변

셸(및/ bash)의 용도는 다른 명령을 실행하는 것이기 때문에 답이 하나만 있는 것은 아닙니다!!

기능
    1. xargs
    2. while read 마디
    3. while read -u대화형 처리를 위해 전용 사용(표본)
인라인 생성 스크립트를 사용하여 셸

OP 요청 관련: 파일나열된 모든 대상에서 실행,xargs는 표시된 도구입니다.그러나 일부 다른 애플리케이션의 경우 소량의 파일 등...

전체 파일을 명령줄 인수로 읽습니다.

파일이 너무 크지 않고 모든 파일의 이름이 제대로 지정되어 있으면(공백 또는 따옴표와 같은 특수 문자 없이) 셸 명령줄 확장을 사용할 수 있습니다.단순:

chmod 755 $(<file.txt)

파일(줄)의 양이 적을 경우 이 명령은 더 가벼운 명령입니다.

1. xargs입니다.

더 많은 양의 파일 또는 입력 파일에 있는 거의 모든 줄의 경우...

많은 비뉴틸리스 도구의 경우, 예를 들어chown,chmod,rm,cp -t...

xargs chmod 755 <file.txt

발견된 파일의 파이프 뒤에 사용할 수 있습니다.find:

find /some/path -type f -uid 1234 -print | xargs chmod 755

특수 문자 및/또는 줄이 많은 경우file.txt.

xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)

find /some/path -type f -uid 1234 -print0 | xargs -0 chmod 755

각 항목에 대해 명령을 정확히 한 번 실행해야 하는 경우:

xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)

에,▁as와 같이 필요하지 않습니다.chmod에서는 여러 개의 파일을 인수로 허용하지만 이는 질문 제목과 일치합니다.

일부 특수한 경우에는 다음 명령에 의해 생성된 명령에서 파일 인수의 위치를 정의할 수도 있습니다.xargs:

xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)

으로 seq 1 5입력으로서

사용해 보십시오.

xargs -n 1 -I{} echo Blah {} blabla {}.. < <(seq 1 5)
Blah 1 blabla 1..
Blah 2 blabla 2..
Blah 3 blabla 3..
Blah 4 blabla 4..
Blah 5 blabla 5..

명령이 한 줄에 한 번씩 실행됩니다.

2. while read및 변형.

이 경우 파일을 줄 바꿈 문자로 끝맺어야 합니다.

OP가 제안하는 바와 같이,

cat file.txt |
while read in; do
    chmod 755 "$in"
done

작동하지만 다음 두 가지 문제가 있습니다.

  • cat |쓸모없는 포크야, 그리고

  • | while ... ;done그 후에 환경이 사라질 하위 셸이 될 것입니다.;done.

그래서 이것은 더 잘 쓰여질 수 있습니다.

while read in; do
    chmod 755 "$in"
done < file.txt

그렇지만

  • 에 대해 경고를 받을 수 있습니다.$IFS그리고.readflags:

help read

read: read [-r] ... [-d delim] ... [name ...]
    ...
    Reads a single line from the standard input... The line is split
    into fields as with word splitting, and the first word is assigned
    to the first NAME, the second word to the second NAME, and so on...
    Only the characters found in $IFS are recognized as word delimiters.
    ...
    Options:
      ...
      -d delim   continue until the first character of DELIM is read, 
                 rather than newline
      ...
      -r do not allow backslashes to escape any characters
    ...
    Exit Status:
    The return code is zero, unless end-of-file is encountered...

경우에 따라 다음을 사용해야 할 수 있습니다.

while IFS= read -r in;do
    chmod 755 "$in"
done <file.txt

이상한 파일 이름의 문제를 방지하기 위해.UTF-8에 문제가 발생할 수도 있습니다.

while LANG=C IFS= read -r in ; do
    chmod 755 "$in"
done <file.txt

입력에서 에▁while동안는하.for reading file.txt', 스크립트가 다른 입력을 대화형으로 읽을 수 없습니다(다른 입력에는 더 이상 표준 입력을 사용할 수 없습니다).

3. while read전용으로

구문:while read ...;done <file.txt표준 입력을 수신 위치로 리디렉션합니다.file.txt즉, 프로세스가 완료될 때까지 프로세스를 처리할 수 없습니다.

이렇게 하면 두 개 이상의 입력을 동시에 사용할 수 있으며, 두 개의 파일(예: scriptReplay)을 병합할 수 있습니다.sh) 또는 아마도:

대화형 도구를 만들려면 표준 입력을 사용하지 않고 대체 파일 설명자를 사용해야 합니다.

상수 파일 설명자는 다음과 같습니다.

  • 표준 입력의 경우 0
  • 표준 출력의 경우 1
  • 표준 오차의 경우 2.

3. 쉘 먼저

다음을 통해 확인할 수 있습니다.

ls -l /dev/fd/

또는

ls -l /proc/$$/fd/

여기서 0에서 63 사이의 사용되지 않은 숫자를 선택해야 합니다(실제로, 다음과 같은 경우).sysctl파일 설명자로 사용할 수 있습니다.

이 데모에서는 파일 설명자 7을 사용합니다.

while read <&7 filename; do
    ans=
    while [ -z "$ans" ]; do
        read -p "Process file '$filename' (y/n)? " foo
        [ "$foo" ] && [ -z "${foo#[yn]}" ] && ans=$foo || echo '??'
    done
    if [ "$ans" = "y" ]; then
        echo Yes
        echo "Processing '$filename'."
    else
        echo No
    fi
done 7<file.txt

입력 파일을 다른 단계에서 읽으려면 다음을 사용해야 합니다.

exec 7<file.txt      # Without spaces between `7` and `<`!
# ls -l /dev/fd/

read <&7 headLine
while read <&7 filename; do
    case "$filename" in
        *'----' ) break ;;  # break loop when line end with four dashes.
    esac
    ....
done

read <&7 lastLine

exec 7<&-            # This will close file descriptor 7.
# ls -l /dev/fd/

3.2 에서도 동일

bash 에서, 당신은 그가 당신을 위해 무료를 선택하게 하고 변수에 저장할 수 있습니다.
exec {varname}</path/to/input:

while read -ru ${fle} filename;do
    ans=
    while [ -z "$ans" ]; do
        read -rp "Process file '$filename' (y/n)? " -sn 1 foo
        [ "$foo" ] && [ -z "${foo/[yn]}" ] && ans=$foo || echo '??'
    done
    if [ "$ans" = "y" ]; then
        echo Yes
        echo "Processing '$filename'."
    else
        echo No
    fi
done {fle}<file.txt

또는

exec {fle}<file.txt
# ls -l /dev/fd/
read -ru ${fle} headline

while read -ru ${fle} filename;do
    [[ -n "$filename" ]] && [[ -z ${filename//*----} ]] && break
    ....
done

read -ru ${fle} lastLine

exec {fle}<&-
# ls -l /dev/fd/

셸 명령 을 위한 입력 파일 필터링

sed <file.txt 's/.*/chmod 755 "&"/' | sh

이렇게 하면 포크가 최적화되지는 않지만, 보다 복잡한(또는 조건부) 작동에 유용할 수 있습니다.

sed <file.txt 's/.*/if [ -e "&" ];then chmod 755 "&";fi/' | sh

sed 's/.*/[ -f "&" ] \&\& echo "Processing: \\"&\\"" \&\& chmod 755 "&"/' \
    file.txt | sh

네.

while read in; do chmod 755 "$in"; done < file.txt

이 방법을 사용하면 다음을 피할 수 있습니다.cat과정.

cat이런 목적에는 거의 항상 나쁜 것입니다.여러분은 고양이의 쓸모없는 사용에 대해 더 읽을 수 있습니다.

좋은 선택기(예: dir의 모든 .txt 파일)가 있으면 다음을 수행할 수 있습니다.

for i in *.txt; do chmod 755 "$i"; done

맹렬히 공격함

아니면 당신의 변종:

while read line; do chmod 755 "$line"; done < file.txt

각 행에 대해 명령을 병렬로 실행하려면 GNU 병렬을 사용할 수 있습니다.

parallel -a <your file> <program>

파일의 각 행이 인수로 프로그램에 전달됩니다.기본적으로parallel는 CPU 수만큼 스레드를 실행합니다.그러나 다음을 사용하여 지정할 수 있습니다.-j

입력에 공백이 없는 경우:

xargs chmod 755 < file.txt

경로에 공백이 있을 수 있고 GNU xargs가 있는 경우:

tr '\n' '\0' < file.txt | xargs -0 chmod 755

현재(GNU 리눅스에서)xargs이것에 대한 답은 여전히 있지만...이제 사용할 수 있습니다.-a파일에서 직접 입력을 읽는 옵션:

xargs -a file.txt -n 1 -I {} chmod 775 {}

또한 AWK를 사용하여 파일을 보다 유연하게 처리할 수 있습니다.

awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt

파일에 다음과 같은 필드 구분 기호가 있는 경우:

필드1,필드2,필드3

수행하는 첫 번째 필드만 가져오십시오.

awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt

자세한 내용은 GNU 설명서 https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple 에서 확인할 수 있습니다.

bash에 태그를 지정했지만 Perl도 이를 위한 좋은 방법입니다.

perl -p -e '`chmod 755 $_`' file.txt

정규식을 적용하여 올바른 파일을 가져오는지 확인할 수도 있습니다. 예를 들어 .txt 파일만 처리합니다.

perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt

일이 있는지 " 보기 무슨일미일있 "리하보기 "지고 "이려 "면로 "표를 "백만 "택스 "고옴 "큰면 "됩다 "니기 "꾸하 "에따바 "이붙앞 "어나는 "end하" "미리 "pre "됩▁what "▁to "니 "다 "면 "를 붙이면 .print:

perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt

이 논리는 다른 많은 목표에도 적용됩니다./home/filesystem에서 각 사용자의 .sh_history를 읽는 방법은 무엇입니까?만약 그들이 수천 명이라면요?

#!/bin/ksh
last |head -10|awk '{print $1}'|
 while IFS= read -r line
 do
su - "$line" -c 'tail .sh_history'
 done

여기 스크립트 https://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh 이 있습니다.

언급URL : https://stackoverflow.com/questions/13939038/how-do-you-run-a-command-eg-chmod-for-each-line-of-a-file