저는 Unix 스크립팅을 처음 접했습니다.
첫 번째 줄(예: 로 시작하는 줄)의 일치하는 문자열을 기반으로 HDR
파일 이름을 바꾸고 싶습니다.
File.txt
다음과 같은 텍스트 파일( )이 있습니다 .
HDR##############################1234###
########################################
########################################
아래는 내 코드입니다. 패턴으로 시작하고 HDR
패턴이 있는 파일의 첫 번째 줄에 대해 내 코드에서 더 구체적으로 확인하려면 어떻게 해야 합니까 1234
?5678
if grep -o "1234" File.txt
then mv File.txt Pattern1.txt
echo "File with pattern1 received..."
elif grep -o "5678" File.txt
then mv File.txt Pattern2.txt
echo "File with pattern2 received..."
else
echo "File have no matching pattern..."
fi
답변1
줄을 읽으려면 "read"를 사용하고, 무엇을 할지 결정하려면 "case"를 사용하세요.
{
IFS= read -r Firstline
case "$Firstline" in
("HDR"*"1234"*) mv File.txt Pattern1.txt
echo "File with pattern1 received..." ;;
("HDR"*"5678"*) mv File.txt Pattern2.txt
echo "File with pattern2 received..." ;;
(*) echo "Nothing matched" ;;
esac
} < File.txt
답변2
-n
( --line-number
) 옵션을 사용하여 grep
선을 식별한 다음 case
패턴을 일치시킵니다.
Tmp=$(grep -n "HDR.*[0-9]\{4\}" File.txt)
if [ "${Tmp%:*}" -eq 1 ]
then case "${Tmp#*:}" in
HDR*1234*) NewName="Pattern1";;
HDR*5678*) NewName="Pattern2";;
esac
if [ "$NewName" ]
then mv -- File.txt "$NewName".txt
echo "File with $NewName received..."
else echo "File doesn't have a matching pattern..."
fi
else echo "File doesn't have a pattern in line 1"
fi
답변3
Perl rename
유틸리티를 사용하십시오.
file-rename
참고: Perl 이름 바꾸기는 , perl-rename
, 또는 이라고도 합니다 prename
. 기능과 명령줄 옵션이 완전히 다르고 호환되지 않는 rename
유틸리티와 혼동 하지 마십시오.util-linux
$ rename -n ' BEGIN {
# This block runs only once when the script starts, there's no need
# to redefine these vars on every pass through the loop. File::Rename
# scripts run with `use strict vars`, so we need to be careful about
# variable scope. See `perldoc -f our`
our %patterns=(1234 => "Pattern1.txt", 5678 => "Pattern2.txt");
our $re = "^HDR#+(" . join("|",keys %patterns) . ")#+$";
};
# The remainder of the script runs once for every filename
our (%patterns, $re); # these vars are in File::Rename lexical scope
open(my $fh,"<",$_); my $line=<$fh>; close($fh);
if ($line =~ /$re/) { $_ = $patterns{$1} }' File*
rename(File1.txt, Pattern1.txt)
rename(File2.txt, Pattern2.txt)
(이것은 두 개의 텍스트 파일(샘플 데이터의 복사본)에서 실행되었습니다. File1.txt에는 File.txt 예제와 정확히 동일한 1234가 포함되어 있는 반면 File2.txt는 5678을 포함하도록 편집되었습니다.)
이 -n
옵션을 사용하면 시험적으로 실행되므로 실제로 파일 이름을 바꾸지 않고 수행할 작업만 표시됩니다. 요구사항을 충족하는 것으로 확인되면 삭제 -n
하거나 로 대체하여 자세한 출력을 얻으세요.-v
이 이름 바꾸기 스크립트는 해시를 사용하여 %patterns
검색할 패턴과 이름을 바꿀 패턴이 포함된 파일의 파일 이름을 저장합니다. 변수의 해시 키를 기반으로 정규식을 구성합니다 $re
.
그런 다음 현재 파일 이름을 열고 첫 번째 줄을 읽습니다. 첫 번째 줄이 패턴 중 하나와 일치하면 해당 파일 이름으로 이름이 변경됩니다.
이러한 해시를 사용하면 스크립트를 더 많거나 다른 패턴으로 쉽게 확장할 수 있습니다. 해시 %patterns
(및 그 안의 합계 )를 ^HDR#+(
제외하고는 아무것도 하드코딩되지 않습니다 .)#+$
$re
-f
참고: 또는 옵션을 사용하여 --force
강제로 이름을 바꾸지 않는 한 이름을 바꾸면 기존 파일을 덮어쓰지 않습니다 . 이는 기존 파일과 방금 이름이 변경된 파일 모두에 적용됩니다. 여러 파일에 동일한 패턴이 포함되어 있으면 첫 번째 파일의 이름만 변경됩니다. -f
물론 를 사용하면 기존/이전에 이름이 바뀐 파일을 덮어쓰게 됩니다. 더 나은 대안은 카운터 변수(예: 파일 이름이나 패턴을 키로 사용하는 해시)를 사용하여 파일 이름을 , Pattern1.txt.001
등 Pattern1.txt.002
으로 바꾸는 것입니다.
또는 다음 fileparse()
기능을 사용하십시오파일::기본 이름모듈이 도착했습니다 Pattern1-001.txt
. Pattern1-002.txt
잠시만 기다려주세요.
예를 들어
$ rename -n 'BEGIN {
use File::Basename;
our %seen=();
our %patterns=(1234 => "Pattern1.txt", 5678 => "Pattern2.txt");
our $re = "^HDR#*(" . join("|",keys %patterns) . ")"
};
our(%seen, %patterns, $re);
open(my $fh,"<",$_); my $line=<$fh>; close($fh);
if ($line =~ /$re/) {
my($name,$path,$suffix) = fileparse($patterns{$1}, qr/\.[^.]*$/);
$_ = sprintf "%s-%03i%s", $name, ++$seen{$1}, $suffix
}' File*
rename(File1.txt, Pattern1-001.txt)
rename(File2.txt, Pattern2-001.txt)
rename(File3.txt, Pattern1-002.txt)