여러 디렉터리에 여러 개의 파일이 있고 각 파일의 첫 번째 줄에 잘못된 날짜가 있습니다. sed와 for 루프가 포함된 스크립트를 작성하려고 합니다.
각 파일은 올바른 날짜로 구성된 자체 디렉토리에 있습니다. 예를 들어 파일이 ./2014/06/02/record1에 있을 수 있으며 첫 번째 줄의 날짜를 "2014/06/02"로 바꾸고 싶습니다.
많은 파일이 있으며 각각 고유한 디렉토리가 있습니다. sed와 for 루프를 사용하여 이를 어떻게 달성할 수 있나요?
답변1
모든 파일을 반복하려면 예를 들어 상위 디렉토리에 있고 2014
파일 자체가 다음과 같이 호출된다고 가정합니다 record<something>
.
for pathname in 20[0-9][0-9]/[0-9][0-9]/[0-9][0-9]/record*
do
if [ -f "$pathname" ]; then
# ...
fi
done
이 패턴은 20[0-9][0-9]/[0-9][0-9]/[0-9][0-9]/record*
언급한 모든 경로 이름과 일치하며, 2000에서 2099까지의 최상위 디렉토리만 있다고 가정합니다.
루프에서의 테스트는 $pathname
값이 기존 일반 파일의 경로 이름(또는 해당 파일에 대한 심볼릭 링크)인지 확인하는 것입니다. 패턴이 아무것도 일치하지 않으면 기본적으로 확장되지 않은 상태로 유지됩니다(대부분의 셸에서). 테스트를 통해 이 사실이 드러날 것입니다.
$pathname
위 루프에서 디렉터리 경로를 얻으려면:
dirpath=$( dirname "$pathname" )
또는
dirpath=${pathname%/*}
이 dirname
유틸리티는 지정된 경로 이름에 대한 디렉터리 경로인 문자열을 반환합니다. 이 변수 대체 변형은 마지막 변수 /
의 모든 것을 제거합니다 $pathname
. 이 경우 두 명령 모두 동일한 결과를 생성하지만 사용하는 것이 일반적으로 더 안전합니다(변수 대체가 반환되는 것이 아니라 주어진 문자열을 dirname
반환함 ).a
a/b/
a/b
at 파일의 첫 번째 줄을 $pathname
in 문자열로 바꾸려면 $dirpath
(GNU sed
및 내부 편집 사용):
sed -i -e '1c\' -e "$dirpath" "$pathname"
c
in 명령은 sed
내용 줄을 완전히 삭제하고 그 자리에 다른 내용을 삽입합니다. 여기서는 첫 번째 행에만 적용하고 $dirname
경로 이름의 날짜가 될 결과 문자열을 삽입합니다.
이것을 스크립트에 통합하십시오.
#!/bin/sh
for pathname in 20[0-9][0-9]/[0-9][0-9]/[0-9][0-9]/record*
do
if [ -f "$pathname" ]; then
dirpath=${pathname%/*}
sed -i -e '1c\' -e "$dirpath" "$pathname"
fi
done
파일의 백업 복사본을 테스트합니다.
대체 동등한 구현 사용 (대부분 동일하며 일반 파일에 대한 심볼릭 링크인 파일을 find
처리하지 않습니다 ):record*
find 20[0-9][0-9]/ -type f \
-path '20[0-9][0-9]/[0-9][0-9]/[0-9][0-9]/record*' -exec sh -c '
for pathname do
sed -i -e "1c\\" -e "$( dirname "$pathname" )" "$pathname"
done' sh {} +
이는 솔루션의 첫 번째 변형과 본질적으로 동일한 루프를 따릅니다.
답변2
다음 스크립트를 사용해 보세요.
#!/bin/bash
for YEAR in $(ls -1)
do
echo -n Processing year $YEAR " "
for MONTH in $(ls -1 $YEAR)
do
echo -n month $MONTH " "
for DAY in $(ls -1 $YEAR/$MONTH)
do
echo -n day $DAY
sed -i "1 s#^.*#$YEAR/$MONTH/$DAY#" $YEAR/$MONTH/$DAY/record1
done
done
echo " "
done
참고: 파일 트리 위의 디렉터리에 스크립트를 저장하고 다음과 같이 실행합니다.
~/tree-of-files $ ../change-dates.sh
Processing year 2014 month 06 day 02
Processing year 2017 month 06 day 02
Processing year 2018 month 06 day 02
Processing year 2033 month 06 day 02
~/tree-of-files $
답변3
기존 접근 방식은 약간 다릅니다. 각 파일에서 YYYY/MM/DD 디렉터리 형식을 가정하는 와일드카드 패턴을 사용하여 파일을 반복하고, 다음을 ed
사용하여 첫 번째 줄을 디렉터리 구조를 포함하는 해당 이름으로 변경합니다.
for file in [0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]/*
do
[ -f "$file" ] || continue
ed -s "$file" <<< $'1c\n'"${file%/*}"$'\n.\nw\nq'
done
명령은 ed
다음 구성 요소와 함께 이 문자열로 제공됩니다.
1c
-- 라인 1을 다음으로 변경합니다...${file%/*}
-- 마지막 슬래시 이후에 생성된 변수의 매개변수 확장을 제거합니다file
(타임스탬프/디렉토리 구조 부분만 유지됨)..
--hangec
명령 종료w
--디스크에 파일 쓰기q
——편집 종료