세 개의 다른 하위 디렉터리에 있는 파일을 하나의 파일로 연결하려고 합니다. 각 하위 디렉터리의 파일 이름은 정확히 동일합니다. 루프를 사용하여 하위 디렉터리를 반복한 다음 새 디렉터리의 새로 명명된 연결된 파일에 반복 번호를 입력하고 싶습니다. 예를 들어 디렉터리 구조는 다음과 같습니다.
Foo
|||
||Bar3
|Bar2
Bar1
각 Bar(?) 폴더에는 File1, File2, File3이라는 파일이 포함되어 있습니다.
같은 이름의 파일을 숫자가 포함된 새 이름의 더 큰 파일에 연결하고 싶습니다.
cat Foo/Bar1/File1 Foo/Bar2/File1 Foo/Bar3/File1 > /combined_files/all_file1
cat Foo/Bar1/File2 Foo/Bar2/File2 Foo/Bar3/File2 > /combined_files/all_file2
cat Foo/Bar1/File3 Foo/Bar2/File3 Foo/Bar3/File3 > /combined_files/all_file3
Foo
내가 사용할 수 있는 디렉토리 에서 :
for number in {1..3}
do
cat Bar1/File$number\_* Bar2/File$number\_* Bar3/File$number\_* > combined_files/'all_files'$number
done
exit
하지만 더 많은 수의 Bar 디렉터리와 파일에 대해서는 좀 더 일반적인 스크립트가 필요합니다. 나는 다음과 같은 것을 원한다
files=`ls ./Run1/ | wc -l` #to count the number of files and assign a number
For n in {1..$files}
do
cat Bar1/File$n\_* Bar2/File$n\_* Bar3/File$n\_* > combined_files/'all_files'$n
done
하지만 막혔어요.
답변1
#!/bin/sh
for pathname in Foo/Bar1/File*; do
filename=${pathname##*/}
cat "$pathname" \
"Foo/Bar2/$filename" \
"Foo/Bar3/$filename" >"combined/all_$filename"
done
이는 이름이 일치하는 모든 파일을 반복합니다 File*
( Foo/Bar1
패턴이 실제로 관심 있는 이름과 정확히 일치한다고 가정합니다).
이러한 각 파일에 대해 생성된 경로 이름의 파일 이름 부분을 추출합니다 (이 작업은 다음을 사용 $filename
하여 수행할 수도 있음). filename=$(basename "$pathname")
그런 다음 Foo/Bar2
원본 파일을 및 디렉터리의 해당 파일과 연결하여 Foo/Bar3
결과를 all_$filename
다른 디렉터리의 새 파일에 씁니다.
일부 오류 확인 후:
#!/bin/sh
for pathname in Foo/Bar1/File*; do
if [ ! -f "$pathname" ]; then
printf '% is not a regular file, skipping\n' "$pathname" >&2
continue
fi
filename=${pathname##*/}
if [ -f "Foo/Bar2/$filename" ] &&
[ -f "Foo/Bar3/$filename" ]
then
cat "$pathname" \
"Foo/Bar2/$filename" \
"Foo/Bar3/$filename" >"combined/all_$filename"
else
printf 'Missing %s or %s\n' "Foo/Bar2/$filename" "Foo/Bar3/$filename" >&2
fi
done
하위 디렉토리 수가 다른 BarN
변형 도 허용됩니다. 이것은추정각 BarN
디렉토리에는 1부터 큰 숫자까지 번호가 매겨져 있습니다.
#!/bin/sh
# This is just used to count the number of BarN subdirectories.
# The number of these will be $#.
set -- Foo/Bar*/
for pathname in Foo/Bar1/File*; do
filename=${pathname##*/}
n=1
while [ "$n" -le "$#" ]; do
if [ ! -f "Foo/Bar$n/$filename" ]; then
printf '%s missing, %s will be incomplete\n' \
"Foo/Bar$n/$filename" "combined/all_$filename" >&2
break
fi
cat "Foo/Bar$n/$filename"
n=$(( n + 1 ))
done >"combined/all_$filename"
done
답변2
@Kusalananda와 @Debian_yadav에게 다시 한 번 감사드립니다. 내 시스템에서 스크립트를 실행할 수 있습니다. 내 실제 디렉터리 이름은 다음과 같습니다.
Joes ||| ||Run3 |Run2 Run1
각 RunX 디렉터리에서 이름은 같지만 내용이 다른 파일을 만들었습니다.
실행1\파일1실행2
\파일1실행3
\파일1
먼저 보여드린 간단한 스크립트를 실행하고 디렉터리 구조를 약간 수정했습니다.
답변
#!/bin/bash
for pathname in Run1/File*; do
filename=${pathname##*/}
cat "$pathname" \
"Run2/$filename" \
"Run3/$filename" > "RunCat/all_$filename"
one
스크립트 출력은 다음 내용을 포함하는 "allFile1" 파일입니다.
123
귀하의 더 긴(최종) 스크립트(K2script.sh라는 이름)도 내 시스템에서 작동합니다.
디렉터리 구조를 약간 수정한 후에도 출력은 다시 정확히 동일합니다.
답변
#!/bin/sh
# This is just used to count the number of RunN subdirectories.
# The number of these will be $#.
set -- Joes/Run*/
for pathname in Run1/File*; do
filename=${pathname##*/}
n=1
while [ "$n" -le "$#" ]; do
if [ ! -f "Run$n/$filename" ]; then
printf '%s missing, %s will be incomplete\n' \
"Run$n/$filename" "RunCat/all_$filename" >&2
break
fi
cat "Run$n/$filename"
n=$(( n + 1 ))
done >"RunCat/all_$filename"
done
또는
또 다른 스택교환 토론
답변
폴더 이름을 변경하면 내 시스템에서 작동하게 되었습니다.
#!/bin/bash
for FILE in Run1/* ; do
FILE2=Run2/${FILE#*/}
FILE3=Run3/${FILE#*/}
if [ -f $FILE2 ] ; then
cat $FILE $FILE2 $FILE3 > RunCat/${FILE#*/}
fi
done
while [ "$n" -le "$#" ]; do
작동 방식 에 대해 많이 읽었 지만 다른 와일드카드나 정규 표현식이 작동하지 않는데 왜 작동하는지 ${pathname##*/}
잘 이해할 수 없습니다 .${FILE#*/}