problema com Else statment no Bash

2

Eu tenho este código simples que cria arquivos .bak quando limpo. arquivos bak devem ser removidos quando eu limpo novamente e não há. bak ele deve ecoar "não há .bak" mas só executa a condição if. Aqui está o código:

#!/bin/bash
chmod u+x sources/*
if [ "$1" == "clean" ]
then

    if [ -f 'sources/*.bak' ]
    then        
       rm sources/*.bak

    else
        echo "there's no .bak files"
    fi

elif ["" == "$1"]
then

echo "This script makes a backup for each .c or .h file in sources directory"

target_files='echo -n $(ls sources/{*.c,*.h})'
echo
echo "Starting to backup: $target_files"

for i in $target_files 
do 
  cp "$i" "$i".bak
done

echo
echo "The following backup files were created: 'echo -n $(ls sources/*.bak)'"
echo
echo "Done"

fi 
    
por N. Nasser 12.01.2017 / 12:04

1 resposta

4

o problema é a linha

if [ -f 'sources/*.bak' ]

backticks ' tem um significado especial no bash: eles são usados para avaliar um comando e retornar sua saída.

Por exemplo Se seu nome de usuário for frodl ,

if [ -f 'whoami' ]

irá verificar se existe um arquivo chamado frodl .

Portanto, se você escrever sources/*.bak , ele tentará primeiro agrupar o termo sources/*.bak , mas como não há arquivos no diretório sources/ com uma extensão .bak , o termo não será expandido. Em seguida, ele tentará executar o termo literal sources/*.bak , que não é um comando válido (na verdade, você pode ter um arquivo chamado sources/*.bak (um nome de arquivo com um asterisco no início; shudder!) mas parece que não, mas este arquivo teria uma extensão .bak , algo que descartamos antes.)

Se você tiver um arquivo sources/deletemyharddisk.bak , o termo sources/*.bak será expandido para essa sequência e, em seguida, tentará executá-lo (potencialmente excluindo seu disco rígido).

Então, o que você precisa fazer é usar aspas comuns.

backupfiles=sources/*.bak
if [ "x${backupfiles}" = "xsources/*.bak" ]; then
     echo "no .bak files" 1>&2
else
     echo "there are .bak files"...
fi

Isso tentará primeiro expandir o termo sources/*.bak para a variável backupfiles . Se houver algum arquivo bak, isso se tornará uma string de todos os nomes de arquivos; se não houver nenhum, isso permanecerá na sequência não expandida. Se você comparar o resultado com o literal (não expandido) sources/*.bak , você pode dizer se uma expansão ocorreu (porque há arquivos correspondentes) ou não.

uma abordagem melhor

No entanto, há poucos motivos para primeiro verificar se há arquivos e excluí-los. Uma abordagem mais simples é simplesmente remover todos os arquivos que correspondem a um determinado padrão. find pode fazer isso por você:

find sources/ -maxdepth 1 -type f -name "*.bak" -delete

(isso pesquisará no primeiro nível ( -maxdepth 1 ) do diretório sources/ dos arquivos ( -type f ; em vez de diretórios ou links simbólicos ou outras coisas), que terminam em .bak ( -name "*.bak" ) e em seguida, remova-os ( -delete )

Não analisar ls

Outro problema com o seu código é

target_files='echo -n $(ls sources/{*.c,*.h})'
for i in $target_files 
...

Você deve nunca analisar a saída de ls .

Em vez disso, use algo como

 for i in sources/*.c sources/*h
 do
   #...
 done
    
por 12.01.2017 / 12:20