파일 이름의 일부를 사용하여 복사, 이동 등의 파일 범위를 선택하고 싶습니다.
무작위 예시 목록:
- α1a
- α2aa
- alpha3abc
- 브라보 A1
- 브라보 B2bb
- 백인
- DeltaA1FDFD
- DeltaA2 다파
- 델타 A2222
- δC1
- ...(다른 파일 묶음)
alpha2*에서 deltaA*까지 일부 명령을 실행하고 싶습니다. 그러면 목록에서 2-9가 선택됩니다. 이렇게 하면 실제로 파일이 몇 개 있는지 걱정하지 않고 이름을 기준으로 범위를 선택할 수 있으며 추가 콘텐츠도 얻을 수 없습니다.
답변1
start=alpha2*
end=deltaA*
for file in *
do
if [[ $file > $start && ( $file < $end || $file == $end ) ]]; then
echo $file
fi
done
에코 대신 배열에 파일을 저장할 수 있습니다.
array+=($file)
그런 다음 배열을 사용하여 파일을 복사, 이동하거나 단순히 for 루프에서 명령을 실행하세요.
답변2
쉘 프로그래밍은 사전 편찬 비교에 그리 좋지 않습니다. Bash, ksh 또는 zsh에서는 사용할 수 있습니다<
조건부 연산자두 문자열을 비교합니다(POSIX sh에는 숫자 비교만 있습니다).
run_in_range () {
start_at="$1"; end_before="$2"; command="$3"; shift 3
for item do
if [[ ! ($x < $start_at) && ($x < $end_before) ]]; then
"$command" "$item"
fi
done
}
run_in_range alpha2 deltaB some_command *
첫 번째 제외 항목을 두 번째 인수로 사용한다는 점에 유의하세요. 는 deltaB
로 시작하는 모든 문자열 다음으로 가장 작은 문자열입니다 deltaA
. deltaA
매개변수로 전달하고 싶다면 그렇게 할 수 있습니다.
run_in_inclusive_range () {
start_at="$1"; end_on_prefix="$2"; command="$3"; shift 3
for item do
if [[ ! ($x < $start_at) && ($x < $end_on_prefix || $x == "$end_on_prefix"*) ]]; then
"$command" "$item"
fi
done
}
run_in_inclusive_range alpha2 deltaA some_command *
이 코드는 와일드카드의 순서에 의존하지 않습니다. 항목 목록이 정렬되지 않은 경우에도 작동합니다. 이렇게 하면 코드가 더욱 강력해지지만 전체 목록을 반복해야 하므로 약간 느려집니다.
이는 POSIX 기능에만 의존하는 대체 방법입니다. sort
문자열 비교 에 사용됩니다 . 이는 프로젝트에 개행 문자가 없다고 가정합니다. 이 기능은 기본 설정을 복원하고 글로빙합니다 IFS
(환경 설정 복원은 가능하지만 성가시게 어렵습니다).
run_in_range () {
IFS='
'; set -f
start_at="$1"; end_before="$2"; command="$3"; shift 3
set $({
printf '%s1\n' "$@"
printf '%s0\n' "$start_at" "$end_before"
} | sort | sed '/0$/,/0$/ s/1$//p')
unset IFS; set +f
for item do
"$command" "$item"
done
}
설명하다:
1
추가 항목 과 추가 경계를 사용하여 목록을 구성합니다0
.- 목록을 정렬합니다.
- 두 경계선( 로 끝나는 라인
0
) 사이의 라인을 인쇄하지만, 로 끝나는 라인1
(즉, 항목)만 인쇄하고 후행1
.
답변3
제 생각에는 이 문제는 보기보다 해결하기가 더 쉽습니다.
한 줄에 파일 하나씩 목록을 얻는 방법이 있다고 가정해 보겠습니다.
현재 디렉터리의 경우:
list="$(printf '%s\n' *)"
목록에 제한을 추가하고 정렬하면 됩니다.
nl='
'
lim1="alpha2"
lim2="deltaA"
echo -- "$list""$nl""$lim1""$nl""$lim2" | sort
그런 다음 lim1에서 인쇄를 시작하고(lim1과 lim2는 기존 파일 이름과 일치하지 않음) lim2에서 중지합니다.
또한 간단하게 하려면 인쇄하려는 파일 앞에 가장 짧은 문자열을 선택하고 선택해야 하는 마지막 파일 뒤에 정렬된 가장 짧은 문자열을 선택하세요.
유용한 것은 배타적 목록(제한 사항을 포함하지 않는 목록)
이지만 두 가지 솔루션을 제공합니다.
기본 값:
list="$(printf '%s\n' *)"
lim1=alpha2
lim2=deltaA
awk를 사용하여 목록이 포함된 솔루션을 얻으세요.
echo "awk----------------inclusive"
echo "$list""$nl""$lim1""$nl""$lim2" | sort |
awk -v lim1="$lim1" -v lim2="$lim2" '$0==lim1,$0==lim2{print}'
awk를 사용하여 독점 목록을 얻는 솔루션:
echo "awk----------------exclusive"
echo "$list""$nl""$lim1""$nl""$lim2" | sort |
awk -v lim1="$lim1" -v lim2="$lim2" '$0==lim1{p=1;next};$0==lim2{p=0};p'
목록이 포함된 셸을 사용한 솔루션:
echo "shell---------------inclusive"
show=0
echo "$list""$nl""$lim1""$nl""$lim2" | sort |
while IFS="$nl" read -r line; do
[ "$line" = "$lim1" ] && show=1
[ "$show" = "1" ] && printf '%s\n' "$line"
[ "$line" = "$lim2" ] && show=0
done
쉘을 위한 독점 솔루션:
show=0
echo "$list""$nl""$lim1""$nl""$lim2" | sort |
while read -r line; do
[ "$line" = "$lim2" ] && show=0
[ "$show" = "1" ] && printf '%s\n' "$line"
[ "$line" = "$lim1" ] && show=1
done