echo, xargs 및 cp를 사용하여 한 파일의 출력을 여러 파일에 복사하려고 합니다. 내 문제는 xargs가 배열의 첫 번째 파일에만 인쇄하고 3개 파일 모두의 복사본에는 인쇄하지 않는다는 것입니다. xargs를 잘못 사용하고 있거나 구문이 올바르지 않습니다. 나는 며칠 동안 이 작업을 해왔고 지금까지 여러 Google 페이지에서 운이 없었습니다. 어떤 도움이라도 대단히 감사하겠습니다!
#!/bin/bash
NF1=/home/user3/mynewfile
U3=/home/user3/
File=(grades mynewfile mynewfile1 mynewfile2)
mkdir -p /home/user3/{CIT/{tests/,grades/},MyStuff/{Tests/,Labs/},NOS/};
echo /etc/hosts.allow > $NF1;
echo $U3/CIT/tests/${File[*]} $U3/CIT/grades/${File[2]} | xargs -n 1 cp $NF1
답변1
구문과 관련이 있다고 의심되는 경우 다른 문제도 발견하여 사용을 완전히 버리고 루프를 xargs
선호하는 버전을 생각해 냈습니다 for
.
#!/bin/bash
U3=/home/user3/
NF1=/home/user3/mynewfile
File=(grades mynewfile mynewfile1 mynewfile2)
mkdir -p /home/user3/{CIT/{tests,grades},MyStuff/{Tests,Labs},NOS};
echo /etc/hosts.allow > $NF1;
for i in "${File[@]}"; do
cp $NF1 $U3/$i
done
cp $NF1 $U3/CIT/grades/${File[2]}
mkdir
불필요한 후행 슬래시를 제거하기 위해 행이 단순화되었으며mkdir
후행 슬래시 유무에 관계없이 디렉토리를 계속 활성화하므로 더 이상 입력이 필요하지 않습니다.
남은 변경 이유:
중복 슬래시
원본 코드 몇 줄을 먼저 테스트하는 경우:
$ U3=/home/user3/
$ File=(grades mynewfile mynewfile1 mynewfile2)
$ echo $U3/CIT/grades/${File[2]}
/home/user3//CIT/grades/mynewfile1
저장된 경로에는 $U3
후행 슬래시가 설정되어 있고 $U3/CIT/grades/${File[2]}
해당 줄 뒤에도 슬래시가 있어 $U3
bash가 이를 로 확장하게 됩니다 . 이는 이중 슬래시가 예 를 들어 불평할 수 있는 것과 동일하지 않기 /home/user3//CIT/grades/mynewfile1
때문에 문제가 됩니다 .//
/
cp
no such file or directory
따라서 단일 슬래시를 참조하는 경우 먼저 후행 슬래시 없이 /
설정하는 것이 좋습니다 .$U3
$ U3=/home/user3
$ File=(grades mynewfile mynewfile1 mynewfile2)
$ echo $U3/CIT/tests/${File[2]}
/home/user3/CIT/tests/mynewfile1
이제 추가 슬래시 없이 올바른 경로가 생성됩니다.
잘못된 지원 확장
수정 후 다음 오류는 다음과 같습니다.
$ echo $U3/CIT/tests/${File[*]}
/home/user3/CIT/tests/grades mynewfile mynewfile1 mynewfile2
나는 당신이 쉼표를 사용한 중괄호 확장과 같은 일반적인 접두사를 File
사용하여 배열의 파일 이름을 확장하려고 한다고 추측합니다 ./home/user3/CIT/tests
$ echo tweedle{dum,dee}
tweedledum tweedledee
이런 형태의 버팀대 확장에서는
- 중괄호
{
바로 앞이나 뒤}
또는 둘 다에 문자열을 올바르게 적용한 것입니다. - 그러나
word
, 쉼표를 사용하여 다른 단어 등을 사용합니다.,
- 하지만 당신은 을 넣었습니다
${File[*]}
. 배열 내용을 이런 식으로 처리하는 것을 본 적이 없습니다.
$U3
대신, 동일한 공통 시작 단어 또는 문자열( )과 배열( )에 따라 다른 다른 부분으로 구성된 목록을 출력하려면 루프를 $File
사용하는 것이 좋습니다 .for
$ for i in "${File[@]}"; do
> echo $U3/$i
> done
입력할 필요가 없으며 >
bash는 줄 연속을 나타내기 위해 자동으로 제공합니다. 스크립트에서는 다음을 수행합니다.
for i in "${File[@]}"; do
echo $U3/$i
done
결과는 언제나
/home/user3/grades
/home/user3/mynewfile
/home/user3/mynewfile1
/home/user3/mynewfile2
- 에서
for i in "${File[@]}"; do
따옴표( )와 플러스는"
루프가 배열의 각 파일 이름을 별도의 인수로 올바르게 이해하도록 하는 데@
중요합니다 .for
$File
시험
최종 목표는 변수가 참조하는 단일 파일을 plus 배열 plus $NF1
의 확장으로 정의된 여러 위치 에 복사하는 것입니다.$U3
$File
$U3/CIT/tests/${File[2]}
이 경우 가장 좋은 방법은 echo 및 실행하려는 명령을 사용하여 테스트하는 것입니다. cp
따라서 set
먼저 테스트를 수행해 보겠습니다.
$ NF1=/home/user3/mynewfile
그 다음에
$ for i in "${File[@]}"; do
> echo cp $NF1 $U3/$i
> done
cp /home/user3/mynewfile /home/user3/grades
cp /home/user3/mynewfile /home/user3/mynewfile
cp /home/user3/mynewfile /home/user3/mynewfile1
cp /home/user3/mynewfile /home/user3/mynewfile2
$U3/CIT/grades/${File[2]}
또한, 잊지 않도록 복사하고 싶은 것 같으니 추가 행으로 추가하세요.
$ echo cp $NF1 $U3/CIT/grades/${File[2]}
cp /home/user3/mynewfile /home/user3/CIT/grades/mynewfile1
- 이것은 모두
cp
실행될 명령에 해당합니다. xargs
원본 코드와 유사한 방식으로 매개변수를 사용하도록 다시 작성할 수 있지만 실제로는 더 많은 입력이 필요하므로 이를 피합니다.
echo
따라서 이 문서의 예제에 있는 항목을 삭제하여 코드의 최종 버전을 생성하세요.
답변2
내가 작성한 스크립트에 어떤 문제가 있는지 모르겠습니다. don_crissti가 지적했듯이 set -x
스크립트로 사용된 두 번째 줄은 디버깅을 위한 좋은 시작점입니다. 문제가 무엇인지 한눈에 확인할 수 있을 만큼 xargs 및 배열 확장에 대해 충분히 알지 못합니다.
하지만, 간단한 해결 방법이 있습니다.이 문제를 해결하는 더 좋은 방법어쨌든: 을 사용하면 tee
하나의 명령으로 여러 파일에 쓸 수 있으며 원하는 경우 파일 내용을 바꾸는 대신 텍스트를 추가할 수도 있습니다.
스크립트를 올바르게 읽었다면 원하는 내용은 다음과 같아야 합니다.
#!/bin/bash
NF1=/home/user3/mynewfile
U3=/home/user3/
File=(grades mynewfile mynewfile1 mynewfile2)
mkdir -p /home/user3/{CIT/{tests/,grades/},MyStuff/{Tests/,Labs/},NOS/};
cd ${U3}CIT/tests/
echo /etc/hosts.allow | tee ${File[*]} ${U3}CIT/grades/${File[2]} $NF1
cd -
cd
편집: 배열 확장은 기본적으로 공백으로 구분되어 있으므로 현재 작업 디렉터리가 아닌 /home/user3/CIT/tests에 생성될 "mynewfile, mynewfile1, mynewfile2" 파일을 추가했습니다 . (물론 이 작업을 수행하는 더 깨끗한 방법이 있습니다.)