파일 이름을 기반으로 배열을 만들려고 하는데 공백에 문제가 있습니다. 이것은 매우 일반적인 것 같습니다. 하지만 - 내가 알 수 있는 한 - 따옴표는 올바르게 설정되었으며 배열이 어떻게 구성되는지 추측합니다.
to_dump="$(find . -maxdepth 1 -print0 )"
to_dump_array=($to_dump)
read -p " -> " final
case "$final" in
a) for drop in "${to_dump_array[@]}" ;
do cp "$drop" --recursive --force Destination_Folder && \
echo "dropped \"$drop\" ;
done ;;
b) echo "Won't drop anything" ;;
esac
조회 쿼리에서 배열을 작성하는 더 좋은 방법이 있어야 한다고 생각합니다. 또한 내가 또 어디로 잘못 가고 있습니까?
답변1
-print0
$(...)
bash 변수의 문자열은 null로 끝나기 때문에 대체에 사용하면 안 됩니다 .
나는 이 질문이 묻는 것과 비슷한 대답으로 질문을 했습니다.https://stackoverflow.com/a/30469553/1091693
다음 답변을 귀하의 질문에 맞게 조정하세요.
to_dump=()
while IFS= read -r -d ''; do
to_dump+=( "$REPLY" )
done < <(find . -maxdepth 1 -print0)
그러면 이름이 지정된 배열이 생성되고 to_dump
이 read
명령을 사용하여 배열에서 NULL로 구분된 요소를 읽습니다 find
. 여기서 파이프 대신 사용하는 이유는 < <(...)
배열이 수정되는 것을 방지하는 암시적 하위 쉘을 피하기 위한 것입니다.
원래 find
명령에 하나가 필요할 수도 -mindepth 1
있고 .
재귀적으로 복사하게 될 (현재 디렉터리)를 선택할 수도 있다는 점은 주목할 가치가 있습니다.
나는 당신이 -maxdepth 1
find를 위한 인수로 사용했다는 것을 알았습니다. 아마도 이것이 더 유용할 것입니다:
shopt -s nullglob
to_dump=( * .[!.]* ..?* )
피하십시오 find
. 이것은 bash 내장만 사용하고 포크하지 않으며 대부분 매우 깨끗합니다.
첫 번째 줄 shopt -s nullglob
은 이 옵션을 활성화하는 bash(-only) 명령입니다 nullglob
. 옵션은 아래에 설명되어 있습니다 man 1 bash
.
설정된 경우, bash는 어떤 파일과도 일치하지 않는 패턴(위의 경로 이름 확장 참조)이 자신이 아닌 빈 문자열로 확장되도록 허용합니다.
간단히 말해, 입력한 파일이 *
파일과 일치하지 않으면 삭제됩니다 *
. 기본 동작은 *
어쨌든 해당 파일을 넣는 것입니다.
두 번째 줄은 배열에 3개의 구체를 추가합니다.
*
: 다음으로 시작하지 않는 모든 파일.
.[!.]*
.
: 하나와 하나의 비문자로 시작하는 모든 파일입니다.
. 이는 일치.
와 디렉토리를 피하기 위한 것입니다..
...?*
..
: 하나 이상의 문자로 시작하는 모든 파일입니다. 이를 추가하는 이유는 이전 glob과 동일하며 누락된 경우를 포함합니다.
Bash는 glob을 배열 정의로 확장하고 올바르게 확장합니다. 공백이나 이와 유사한 분할이 없습니다.
nullglob 사용에 대한 경고: nullglob을 켜면 curl google.com/search?q=test
컬이 인수를 전달하지 않았다고 불평하고 ls /var/fasdfasafs*
현재 디렉터리 목록을 제공합니다. 이것이 기본적으로 켜져 있지 않은 이유 중 하나입니다.
답변2
다음과 같이 배열을 만들어 보십시오.
read -d $'\0' -r -a to_dump <<< $(find . -maxdepth 1 -print0)
답변3
find . -maxdepth 1
...당신이 원하는 것은 다음과 같습니다.
a=()
for f in ./..?* ./.[!.]* ./*
do [ -e "$f" ] && a+=$f
done
답변4
귀하의 스크립트가 귀하가 생각하는 대로 작동하는지 잘 모르겠습니다. 나는 이것이 null로 끝나는 find 출력을 파일 이름의 bash 배열로 변환한다고 생각하지 않습니다.
to_dump_array=($to_dump)
for 루프의 출력을 확인하여 결과를 확인했습니까?
for drop in "${to_dump_array[@]}"
do
echo -e "$drop\n"
done
find -print0에서 배열을 채우는 방법에 대한 몇 가지 조언이 포함된 스택 오버플로가 있습니다.
https://stackoverflow.com/questions/1116992/capturing-output-of-find-print0-into-a-bash-array
for 루프의 변수에 직접 할당하는 것보다 배열 항목에 대해 배열 인덱싱을 사용하는 것이 더 나을 수도 있습니다. 이렇게 하면 적절한 분할을 위해 셸에 의존하지 않아도 됩니다.
for drop in $(seq 0 $((${#to_dump_array[@]} - 1)))
do
cp "${to_dump_array[$drop]}"
이것은 그다지 인기가 없을 수도 있지만, 파일 이름에서 공백(및 기타 특이한 문자)을 관리하기 위해 bash 배열과 여러 이스케이프를 사용해야 하는 경우 쉘이 설계된 목적을 초과할 수 있습니다.
Python, Perl, Ruby 등이 더 빠르고 안정적이며 코드 기반을 관리하고 디버깅하기가 더 쉽다는 것을 알 수 있습니다.
나는 쉘 스크립팅에 적합한 수준을 넘어서는 경우를 알려주는 데 사용하는 여러 가지 "위험 신호"를 가지고 있습니다.
- 모든 파일 이름 상황을 처리하기 위한 여러 수준의 이스케이프 또는 null 종료.
- 여러 계층의 셸 함수가 서로 호출합니다.
- 복잡한 데이터 구조. 즉, 문자열과 숫자를 넘어서는 것입니다.
- 나는 "성능 최적화"를 수행하고 있습니다.
- 표현식의 "라인 노이즈".
예, 위의 모든 작업을 확실히 수행할 수 있습니다. 하지만 그렇게 해야 합니까? 정말...파이썬, 펄, 루비 등. Python에서는 매우 간단합니다. 공백이나 이진 문자가 포함된 파일 이름이나 이스케이프에 대해 걱정할 필요가 없습니다.
import os
dirListing = os.listdir("somedirectory")
for eachEntry in dirlisting:
doSomething