디렉터리(및 하위 디렉터리)에 있는 특정 유형의 파일을 나열하는 쉘 스크립트를 작성하려고 합니다. 재귀 부분 때문에 어려움을 겪고 있습니다.
이것이 내가 가진 것입니다:
#!/bin/sh
#download dir
DOWNLOADING_DIR=/Users/richard/Downloads
echo "Starting Script..."
for FILE in $DOWNLOADING_DIR/*
do
if [ -d "$FILE" ]
then
echo "...Checking Directory "$FILE
for DFILE in $FILE/*
do
echo "Found file ... $DFILE"
done
else
echo "Found file ... $FILE"
echo ""
fi
done
문제는 디렉토리를 찾을 때 디렉토리에서 파일 이름을 찾지 못한다는 것입니다. 하위 디렉터리의 파일이 아닌 하위 디렉터리 이름만 나열됩니다. 첫 번째 디렉터리의 파일에 대해 작동합니다.
.txt 또는 .doc 파일을 검색하여 다른 디렉터리로 이동하려면 이 스크립트가 필요합니다.
답변1
귀하의 스크립트는아니요자신을 호출하지 않기 때문에 재귀적입니다.
비슷한 것을 재귀적으로 구현하는 변형은 다음과 같습니다.
#!/bin/bash
walk_dir () {
shopt -s nullglob dotglob
for pathname in "$1"/*; do
if [ -d "$pathname" ]; then
walk_dir "$pathname"
else
printf '%s\n' "$pathname"
fi
done
}
DOWNLOADING_DIR=/Users/richard/Downloads
walk_dir "$DOWNLOADING_DIR"
이 함수는 walk_dir
디렉터리 경로 이름을 유일한 인수로 사용하고 해당 내용을 반복합니다. 디렉터리가 발견되면 하위 디렉터리를 탐색하기 위해 자신을 재귀적으로 호출합니다.
.txt
파일 이름이 또는 로 끝나는 파일을 찾으려면 이 명령을 수정하세요 .doc
.
#!/bin/bash
walk_dir () {
shopt -s nullglob dotglob
for pathname in "$1"/*; do
if [ -d "$pathname" ]; then
walk_dir "$pathname"
else
case "$pathname" in
*.txt|*.doc)
printf '%s\n' "$pathname"
esac
fi
done
}
DOWNLOADING_DIR=/Users/richard/Downloads
walk_dir "$DOWNLOADING_DIR"
위의 "파일"은 실제로 디렉터리나 디렉터리 심볼릭 링크가 아닌 모든 것을 의미하며 디렉터리와 동일하지 않을 수도 있습니다.일반 파일. 에서 dotglob
및 nullglob
쉘 옵션을 설정하면 bash
숨겨진 경로 이름을 찾을 수 있으며 잠재적으로 비어 있는 디렉토리를 특별히 테스트할 필요가 없습니다.
이것의 변형은 /bin/sh
숨겨진 이름에 신경 쓰지 않습니다.
#!/bin/sh
walk_dir () {
for pathname in "$1"/*; do
if [ -d "$pathname" ]; then
walk_dir "$pathname"
elif [ -e "$pathname" ]; then
case "$pathname" in
*.txt|*.doc)
printf '%s\n' "$pathname"
esac
fi
done
}
DOWNLOADING_DIR=/Users/richard/Downloads
walk_dir "$DOWNLOADING_DIR"
globstar
및 exglob
쉘 옵션을 사용하면 bash
다음을 수행하여(재귀 없이) 파일을 이동할 수도 있습니다.
shopt -s globstar extglob
mv "$DOWNLOADING_DIR"/**/*.@(txt|doc) "$destdir"
...결과 파일 목록이 너무 길지 않은 한. **
경로 이름의 슬래시와 일치하고 ( 로 활성화됨 globstar
) *.@(txt|doc)
또는로 끝나는 모든 파일 이름과 일치합니다 .txt
( .doc
로 활성화됨 extglob
).
특정 최상위 디렉터리 안이나 아래로 끝나는 파일 이름을 가진 일반 파일을 찾아서 .txt
다른 디렉터리로 이동하는 보다 효율적이고 이식 가능한 방법입니다..doc
$topdir
$destdir
find "$topdir" -type f \( -name '*.txt' -o -name '*.doc' \) \
-exec mv {} "$destdir" \;
GNU를 사용하면 mv
더 효율적으로 만들 수 있습니다.
find "$topdir" -type f \( -name '*.txt' -o -name '*.doc' \) \
-exec mv -t "$destdir" {} +
이 변경사항은 이전됩니다.일괄한 번에 하나의 파일 대신 파일. mv
with를 사용하여 -v
이동된 내용을 확인하거나 before를 추가하여 -print
라는 -exec
경로 이름 목록을 가져옵니다.mv