como criar um arquivo automaticamente?

1

Estou tentando criar um script que possa:

  • procure por um arquivo contendo "foobar" como nome
  • um script é executado neste arquivo e a saída deve ser armazenada em um novo arquivo CSV, criado automaticamente e com o mesmo nome do arquivo pesquisado. A única diferença é que a extensão é alterada para CSV.

Este é o meu script. :

#!/bin/bash

# search for file containing "foobar" as a name in the directory
for file in /home/user/Documents/* ;
do 

if [[ "$file" == *"$foobar"* ]]; then
touch  /home/user/Documents/collectCSV/csv1.csv
# executing script of modelising foobar file ==> extract some data from $foobar file and insert it in the
# created file csv1.csv
/home/user/scriptModelise.pl  $file >> /home/user/Documents/collectCSV/csv1.csv


else 
echo "foobar file not found" 
fi

done

O problema é que esse método de criação de um arquivo é estático. Eu não consegui fazer a criação automática de arquivos. Quero dizer, quando encontrar um arquivo foobar, ele será modelado em um novo arquivo que será criado.

Alguma ajuda, por favor?

    
por pietà 16.03.2016 / 09:59

3 respostas

1

tente

for file in *"$foobar"*
do
   dest="$(echo $file| sed -e 's/\(.*\)\.[^\.]*$/.csv/' )"
   if test -f "$file" 
   then 
       /home/user/scriptModelise.pl  "$file" >> /home/user/Documents/collectCSV/$dest
   else
     echo "no $foobar file"
   fi
done

onde

  • \(.*\)\.[^\.]*$ captura um padrão com qualquer caractere, (fim do padrão) seguido por um ponto, sem ponto até o final da linha
  • .csv insere o padrão encontrado, adicione .csv

  • *"$foobar"* expandirá para litteral *foobar* (com valor apropriado) se nenhum arquivo correspondente for encontrado. daí a necessidade de test -f "$file"

Editar:

  • \(.*\)\.[^\.]*$ (lado esquerdo: encontrando padrão (s))

dividida em (_ espaço reservado)

  • __.*__________ um padrão com qualquer caractere (o ponto tem um significado especial: qualquer caractere)

  • __.*__\._______ um padrão com qualquer caractere, seguido por um ponto (o ponto de escape é um ponto simples)

  • __.*__\.[^\.]*$ padrão com qualquer caractere, (fim do padrão) seguido por um ponto, sem ponto ( [^\.]* ) até o final da linha (o sinal de dólar é especial para o final da linha)

  • \(__\)__________ captura a primeira parte do padrão.

  • .csv (lado direito, o que fazer)

  • ____ corresponde ao que ficou dentro do primeiro \( \) , para o segundo e assim por diante, use & para todo o padrão.

por 16.03.2016 / 10:26
3

Mais fácil com zsh (observe que você já está usando a sintaxe zsh quando deixa suas variáveis sem aspas assim):

#! /bin/zsh -
files=(/home/user/Documents/*foobar*(N))
if (($#files)) {
  ret=0
  for f ($files) {
    /home/user/scriptModelise.pl $f > $f:h/collectCSV/$f:t:r.csv || ret=$?
  }
  exit $ret
} else {
  echo >&2 No non-hidden foobar file
  exit 1
}
  • Como em csh , $f:h é a cabeça (dirname), $f:t a cauda (nome da base), $f:r a raiz (extensão removida).
  • ((arithmetic expression)) , como em ksh , avalia a expressão aritmética e retorna verdadeiro se for resolvido para um valor diferente de zero.
  • $#array , reminiscente de ksh ${#string} , dá o comprimento da matriz em número de elementos. Em ksh / bash , onde as matrizes não são realmente um tipo distinto, você precisa de ${#array[@]} para isso, pois ${#array} seria o comprimento (em número de caracteres) do elemento do indice 0.
  • (N) : qualificador glob que diz para expandir para nada se não houver correspondência
  • $f , $files : ao contrário de outros shells parecidos com Bourne, as variáveis não precisam ser citadas (contanto que não contenham valores vazios). Em outros shells (ksh, bash, yash), você precisaria de "$f" e "${files[@]}" .
por 16.03.2016 / 11:20
0

Usar o GNU Parallel fará isso facilmente e processará vários arquivos de uma só vez como um bônus:

parallel /home/user/scriptModelise.pl {} ">>" {.}.csv ::: *"$foobar"*

Isso causará um erro se nenhum arquivo corresponder a *"$foobar"* , portanto, você deve verificar isso primeiro ou usar find para canalizar os nomes ou definir a opção failglob do bash.

    
por 16.03.2016 / 12:11