저는 Windows 공유에서 로컬 폴더로 파일을 복사하여 붙여넣는 경우가 많습니다. 이를 위해 파일 이름을 검색하고, 이 검색을 기반으로 선택할 수 있는 메뉴를 갖고, 선택한 파일을 로컬 폴더에 복사할 수 있는 작은 bash 스크립트가 필요합니다. 로컬 공유를 다시 검색하려면 매번 많은 시간이 걸리고 파일이 자주 변경되지 않으므로 filelist.txt
.
선택 메뉴의 여러 도움말 사이트에서 복사하여 붙여넣어 다음 코드를 생각해냈습니다. 그러나 grep 출력 및 선택 메뉴에 문제가 있습니다. 어떻게 든 개행 문자가 인식되지 않고 옵션 #1로 모든 파일 이름 목록이 있고 옵션 #2가 종료됩니다. 이는 스크립트가 grep 출력을 다른 옵션으로 분할하지 않음을 의미합니다.
이 동작을 방지하려면 어떻게 해야 합니까?내가 뭘 잘못했나요? 이 방법으로 grep을 사용할 수 있습니까, 아니면 다른 기능을 사용해야 합니까?
스크립트 example_script
:
#!/bin/bash
read -p 'What are you searching for? ' file_search_name
prompt="Please select a file:"
options=$(grep $file_search_name $HOME/Local/Folder/filelist.txt)
PS3="$prompt "
select opt in "${options[@]}" "Quit" ; do
if (( REPLY == 1 + ${#options[@]} )) ; then
exit
elif (( REPLY > 0 && REPLY <= ${#options[@]} )) ; then
echo "You picked $opt which is file $REPLY"
break
else
echo "Invalid option. Try another one."
fi
done
cp ~/Windows/Share/"$opt" $HOME/Local/Folder/"$opt"
예제 출력:
$ example_script
What are you searching for? File
1) File1.txt
File2.txt
File3.txt
...
2) Quit
Please select a file:
답변1
grep
결과를 문자열이 아닌 배열로 저장해야 합니다 .
options=( $(grep $file_search_name $HOME/Local/Folder/filelist.txt) )
하지만 파일 이름에 공백이 있으면 제대로 작동하지 않습니다. 따라서 mapfile
내장된 기능( help mapfile
자세한 내용 참조)을 사용하고 다음 사항도 수행해야 합니다.변수 참조. 다음은 스크립트의 작업 버전입니다.
#!/bin/bash
read -p 'What are you searching for? ' file_search_name
prompt="Please select a file:"
mapfile -t options < <(grep "$file_search_name" "$HOME/Local/Folder/filelist.txt")
PS3="$prompt "
select opt in "${options[@]}" "Quit" ; do
if (( REPLY == 1 + "${#options[@]}" )) ; then
exit
elif (( REPLY > 0 && REPLY <= "${#options[@]}" )) ; then
echo "You picked $opt which is file $REPLY"
break
else
echo "Invalid option. Try another one."
fi
done
무슨 일이 일어나고 있는지 이해하려면 다음 예를 시도해 보세요.
$ cat file
foo
bar
baz
a line with spaces
이제 당신에 대해 이야기해 봅시다 grep
:a
$ grep a file
bar
baz
a line with spaces
원본 스크립트와 같이 저장하면 다음과 같습니다.
options=$( grep a file)
이것은 단일 문자열입니다. 따라서 ${options[@]}
해당 단일 문자열로 확장하면 다음과 같습니다.
$ for i in "${options[@]}"; do echo "Option: $i"; done
Option: bar
baz
a line with spaces
이제 다시 시도하고 배열로 저장하십시오.
$ options=( $( grep a file) )
$ for i in "${options[@]}"; do echo "Option: $i"; done
Option: bar
Option: baz
Option: a
Option: line
Option: with
Option: spaces
이것이 더 낫습니다. 최소한 문자열보다는 배열이지만 보시다시피 공백을 잘 처리하지 못합니다. 이것이 mapfile
들어오는 곳 입니다 :
$ mapfile -t options < <(grep "$file_search_name" "$HOME/Local/Folder/filelist.txt")
$ for i in "${options[@]}"; do echo "Option: $i"; done
Option: bar
Option: baz
Option: a line with spaces
배열로 읽어온 -t
값에 mapfile
각 입력 행의 후행 개행 문자( )를 포함 하지 않음을 나타냅니다.\n