전체 트리를 통과하여 일부(예: ".@__thumb")를 제외한 모든 숨겨진 파일(예: ".git")을 제거하는 스크립트를 만들고 싶습니다. 나는 내 트리를 통과하여 "."으로 시작하는 모든 파일을 제거하는 스크립트를 만들었습니다.
여기있어:
find . -depth -type d -name '.*' |
while read f
do
dn=`dirname "$f"`
bn=`basename "$f"`
mv "$dn/$bn" "$dn/${bn//.}"
done
그런 다음 폴더/파일 이름이 ".@__thumb"(삭제하고 싶지 않은 폴더)인 경우 ".@__thumb"가 삭제되지 않도록 이를 조정하고 조건을 추가하고 싶습니다.
이해합니다:
thumb=".@__thumb"
echo $thumb
find . -depth -type d -name '.*' |
while read f
do
if [[ $bn != $thumb ]]
then
dn=`dirname "$f"`
bn=`basename "$f"`
mv "$dn/$bn" "$dn/${bn//.}"
fi
done
그러나 내 상황은 도움이 되지 않는 것 같습니다. 내 스크립트는 여전히 ".@__thumb" 폴더를 삭제합니다. 문제가 무엇인지 알고 있거나 개선할 아이디어가 있습니까? 내 설명이 명확한지 모르겠습니다. 궁금한 점이 있으면 주저하지 말고 문의하세요. 매우 감사합니다.
답변1
여기서는 귀하의 질문에서 요구하는 것처럼 디렉토리 자체를 제거하는 대신 (귀하의 코드가 분명히하려고하는 것처럼) 이러한 숨겨진 디렉토리 이름의 선행 점을 제거하고 싶다고 가정합니다.
여기서는 다음을 사용합니다 zsh
.
autoload -Uz zmv
zmv -n '(**/).(^@__thumb)(#qD/)' '$1$2'
만족스러우면 삭제 -n
(테스트 실행)합니다.
을 사용하려면 find
다음을 사용할 수 있습니다.
LC_ALL=C find . -depth -name '.?*' ! -name '.@_thumb' -type d -exec sh -c '
for file do
base=${file##*/}
mv -i -T "$file" "${file%/*}/${base#.}"
done' sh {} +
( mv
GNU를 가정 -T
)
귀하의 접근 방식은 그다지 강력하지 않으며 몇 가지 문제가 있습니다.
- 한 줄을 읽으려면
read
구문은 다음과 같습니다.IFS= read -r line
, 아니요. 그러나 파일 경로는 어쨌든 여러 줄로 구성될 수 있습니다.read line
find
이렇게 출력을 반복 할 수는 없습니다 .. -name '.*'
.
이름이 로 시작하고 뒤에 오는 파일과 일치합니다 .영이상수치. 따라서 자체적으로 일치하며.
로케일에서 유효한 문자를 형성하지 않는 바이트 시퀀스가 포함된 파일 이름을 건너뜁니다. 따라서LC_ALL=C
모든 바이트가 문자인지 확인하고.?*
최소한 하나의 문자(LC_ALL=C
다음 바이트.
)가 있는지 확인하십시오.[[ $a = $b ]]
in은 패턴 과 일치하는지bash
확인합니다 (in의 반대 ). 바이트 간 동등 비교를 위한 표준이 필요합니다 (비록 와일드카드가 포함되어 있지 않으므로 여기서는 차이가 없어야 함).$a
$b
!=
[[ $a = "$b" ]]
[ "$a" = "$b" ]
.@__thumb
`...`
은 더 이상 사용되지 않는 고대 형태의 명령 대체이므로 최신 형태를 사용하는 것이 좋습니다$(...)
. 둘 다 후행 줄 바꿈을 제거하므로 임의의 파일 이름과 함께 사용할 수 없다는 문제가 있습니다. 디렉터리 이름/기본 이름 + 명령 대체 대신 표준sh
${var##*/}
AND 연산자를 사용하면 이러한 문제를 피할 수 있습니다.${var%/*}
- ksh 연산자는 in
${bn//.}
의 모든 항목을 제거합니다 . 따라서 첫 번째 문자만 제거하거나 표준을 사용하여 선행 문자를 제거하기 위해 이름이 . 로 변경됩니다 ..
$bn
.foo.d
food
${bn/.}
${bn#.}
.
- 디렉토리에 a
.foo
와foo
dir이 모두 포함되어 있으면 (이동합니다mv .foo foo
.mv .foo foo/.foo
.foo
입력하다(아니요도착하다)foo
목차).-T
이러한 상황을 피하고 사용을-i
피할 수 있는 기회를 제공합니다 . 모든 온전성 검사는 작업을 수행하기 전에 수행되므로 더 안전합니다.foo
.foo
zmv
- @RalfFriedl이 이미 지적했듯이
$bn
설정하기 전에 참조하십시오! - 그럼에도 불구하고
.git
디렉터리 이름을 바꾸면 해당 상위 디렉터리git
는git
더 이상 git 저장소로 간주되지 않습니다. 이름.bashrc
을 바꾸면 시작 시 등에 더 이상 읽혀지지 않습니다.bashrc
bash
답변2
이는 일반적으로 프로그래밍과 더 관련이 있지만 명령 순서에 주의해야 합니다.
$bn
여기서는 조건부 비교에 값을 사용하지만 나중에 값을 계산합니다.
그러니 시도해 보세요
...
bn=`basename "$f"`
if [[ $bn != $thumb ]]
...