Estou trabalhando em um script que examina uma pasta de lição de casa (os arquivos de origem) e, se a pasta existir, procura uma pasta de destino. Se essa pasta não existir, ela copia a origem para o destino.
Se o destino existir, ele tenta copiar o arquivo da origem para o destino e, antes de fazer isso, avisa primeiro o usuário para que não substitua o trabalho já realizado por esse usuário.
A saída do comando deve estar em um formato específico, portanto não posso usar a saída padrão do comando como está. Devo capturá-lo e reformatá-lo. Em seguida, receba a entrada (ou seja, y/N) em um formato específico.
A vantagem de fazer isso é que o comando copy já faz coisas úteis. Se um arquivo não existir, ele faz a cópia.
Se um arquivo ou vários arquivos já existirem, ele perguntará repetidamente "sobrescrever s/n?" É esse caso que estou tentando lidar.
Cheguei ao ponto de capturar a saída do comando copy em uma variável e suprimir sua saída normal para que eu possa reformatar sua saída e repetir esse formato de volta para o usuário.
Em seguida, meu pensamento é que preciso matar (ou interromper o comando de alguma forma), depois imprimir a saída no formato desejado e, em seguida, invocar novamente o comando e, na segunda vez, posso repetir o prompt y/N em meu formato desejado e o usuário pode então fazer sua escolha. Apesar da pesquisa, não consegui descobrir/entender como matar ou interromper o comando depois de invocado. Eu tentei matar e várias tentativas de usar o SIGINT. Ou simplesmente não entendo como usá-los ou não são a escolha certa. Quando tento usá-los, recebo um erro de sintaxe.
Aqui está o meu código:
#!/bin/bash
USAGE="Usage: ./script2.sh [hw-name]"
EINVALID="Invalid homework: $1"
SOURCEDIRECTORY="$PUBLIC/homework/$1"
HOMEWORKDIRECTORY="$HOME/homework/$1"
COPY="$SOURCEDIRECTORY/*.*"
if [ -z "$1" ]; then
echo $USAGE
exit
fi
if [ ! -d "$SOURCEDIRECTORY" ]; then
echo $EINVALID
exit
fi
if [ ! -d "$HOMEWORKDIRECTORY" ]; then
echo "making homework1"
mkdir -p $HOMEWORKDIRECTORY
copyOutput2="$(eval cp -ir $COPY $HOMEWORKDIRECTORY 2>&1 &stop this
process somehow)"
echo $copyOutput2 #temporary output for testing
Responder1
Se alguém realmente precisa personalizar cp
a mensagem personalizada, então recompilar o programa a partir do código-fonte é o caminho a seguir, mas uma abordagem um pouco mais sensata seria escrever sua própria mensagem de printf
preferência, em vez de tentar interceptar cp
a saída de e lidar com as escolhas do usuário por meio de select
diálogo. Além disso, se você deseja gerar mensagens de erro, elas devem ir para stderr
o stream. Finalmente, *.*
é desnecessário e você pode simplesmente usar *
glob.
Abaixo está o script com algumas edições. Observe que você precisa descomentar #cp "$item" "$HOMEWORKDIRECTORY"
a linha para que a cópia real ocorra. Para fins de teste, substitua cp
pelo echo
primeiro.
#!/bin/bash
USAGE="Usage: ./script2.sh [hw-name]"
EINVALID="Invalid homework: $1"
SOURCEDIRECTORY="$PUBLIC/homework/$1"
HOMEWORKDIRECTORY="$HOME/homework/$1"
#COPY="$SOURCEDIRECTORY/*.*"
if [ -z "$1" ]; then
echo "$USAGE" > /dev/stderr
exit 1
fi
if [ ! -d "$SOURCEDIRECTORY" ]; then
echo "$EINVALID" > /dev/stderr
exit 2
fi
if [ ! -d "$HOMEWORKDIRECTORY" ]; then
echo "making homework1"
mkdir -p $HOMEWORKDIRECTORY
for item in "$SOURCEDIRECTORY"/*; do
skip=true
if [ -f "$HOMEWORKDIRECTORY"/"${item##*/}" ]; then
printf "%s already exists in %s.\n" "$item" "$HOMEWORKDIRECTORY"
select choice in "overwrite" "skip"; do
case "$choice" in
"overwrite") echo "Overwriting."
break;;
"skip") skip=true; break;;
esac
done
fi
if [ "$skip" = "true" ]; then
continue
fi
echo cp "$item" "$HOMEWORKDIRECTORY"
done