나는 글을 쓰고있다배쉬 스크립트이렇게 하면 파일/디렉터리가 기존 디렉터리 경로에서 다른 디렉터리 경로로 이동됩니다. 하지만 for loop
with 문을 사용하는 if condition
동안 일부 확장 파일을 건너뛸 수 없습니다 . 내 스크립트는 오류 없이 실행되지만 거기에 지정한 필수 확장 파일을 건너뛰는 대신 if condition
모든 파일과 디렉터리를 이동합니다. 아래는 제가 작성하려고 하는 스크립트입니다.
내가 뭘 잘못하고 있는지 안내해주세요.
제가 하려는 일은 다음과 같습니다.
#!/bin/env bash
#moving home profile data to another location
echo "Moving Desktop Files"
path=/home/$USER/Desktop/*
for m in $path
do
link=$(basename -s .lnk ${m})
desktop=$(basename -s .desktop ${m})
if [[ "${link}.lnk" == "${m}" ]] || [[ "${desktop}.desktop" == "${m}" ]]
then
echo "skipping link and desktop extension files"
continue
fi
mv -n "$m" /home/$USER/CoreData/HOME/Desktop/
done
답변1
매우 우회적인 방식으로 파일 이름 접미사를 일치시키고 이름에 공백이 있는 파일을 처리할 수 없는 방식으로 루프를 작성했습니다.
귀하의 명령문과 관련된 주요 문제 if
는 $m
경로 이름에 디렉토리 경로 요소가 포함되어 있는 반면 $desktop
및 는 $link
파일 이름으로 해석되면 디렉토리 경로 요소가 없다는 것입니다.
더 안전한 코드에 대한 권장 사항:
#!/bin/bash
for name in "$HOME/Desktop"/*; do
if [[ $name == *.lnk ]] || [[ $name == *.desktop ]]; then
printf 'Skipping "%s"\n' "$name"
else
mv -n -- "$name" "$HOME/CoreData/HOME/Desktop"
fi
done
이는 ==
내에서 일치하는 (와일드카드) 패턴을 사용합니다.[[ ... ]]
bash
개별적으로 이름 globbing을 수행하고 변수에 저장하려면 배열을 사용하십시오.
names=( "$HOME/Desktop"/* )
for name in "${names[@]}"; do ... done
위의 인용문은 개별 경로 이름의 무결성을 유지하는 데 중요합니다.
또는 다음 case ... esac
명령문 을 사용하십시오 /bin/sh
.
#!/bin/sh
for name in "$HOME/Desktop"/*; do
case $name in
*.lnk|*.desktop)
printf 'Skipping "%s"\n' "$name"
;;
*)
mv -n -- "$name" "$HOME/CoreData/HOME/Desktop"
esac
done
마찬가지로 와일드카드를 별도로 사용하시겠습니까?
set -- "$HOME/Desktop"/*
for name do ... done
이는 명명된 배열 대신 위치 매개변수를 사용합니다. 쉘은 sh
명명된 배열을 지원하지 않습니다.
또는 다음을 사용하십시오 rsync
.
rsync --archive --verbose \
--exclude='*.lnk' \
--exclude='*.desktop' \
"$HOME/Desktop/" "$HOME/CoreData/HOME/Desktop"
(그런 다음 "$HOME/Desktop"
필요에 따라 삭제)