Deseja fazer arquivos txt para cada png na pasta

12

Eu tenho esse script

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in $folder/*
do
touch $filePng.txt
done

Funciona, só que, para um arquivo chamado 001.png , ele cria 001.png.txt em vez de 001.txt .

Como posso modificar isso?

    
por Qubix 11.04.2017 / 15:31

5 respostas

16

Você pode usar o comando basename aqui:

touch "$folder/$(basename "$filePng" .png).txt"

Observe o $folder/ adicional. Isso é necessário porque o comando basename remove o caminho de.

    
por Wayne_Yux 11.04.2017 / 15:42
32

Você pode remover a extensão existente usando os recursos de expansão do shell

  

${parameter%pattern} O 'padrão' é comparado com o final do   'parâmetro'. O resultado é o valor expandido de 'parâmetro' com o   correspondência mais curta excluída.

Portanto, no seu caso, substitua $filePng.txt por "${filePng%.png}.txt"

    
por steeldriver 11.04.2017 / 15:45
10

Com a variação do que o steeldriver já mencionou - expansão de parâmetros - podemos usar a substituição de strings para fazer o trabalho. Além disso, você deve citar variáveis. Abaixo está o seu script editado.

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in "$folder"/*
do
    touch "${filePng/.png/.txt}"
done
    
por Sergiy Kolodyazhnyy 11.04.2017 / 20:09
9

Se você tiver muito de arquivos para criá-lo, valeria a pena “tocar” mais de um arquivo por vez, para que você não precise forçar um novo processo para cada um dos arquivos. eles (o que leva algum tempo se for realizado milhares de vezes).

Opção 1: substituição de padrão + xargs

Esta opção fornecerá vários caminhos para o comando touch de uma vez, geralmente alguns milhares ou qualquer que seja o sistema que possa caber em uma única linha de comando.

find "$folder" -mindepth 1 -maxdepth 1 -name '*.png' -print0 |
sed -ze 's/\.png$/.txt/' |
xargs -r0 -- touch --

Opção 2: expansão de parâmetro + redirecionamento de saída de comando

Esta opção não executa touch , mas usa recursos de shell Bash / Bourne / POSIX, que não requerem sub-processos.

for f in "$folder"/*.png; do
    : >> "${f%.png}.txt"
done
    
por David Foerster 11.04.2017 / 19:38
4

Se você tiver certeza de que não tem arquivos com .png em algum lugar no meio do nome, poderá usar apenas uma matriz com a expansão de parâmetros:

pngs=( /path/to/pngs/*.png )
touch "${pngs[@]/.png/.txt}"

Isso armazena todos os caminhos para os arquivos que terminam em .png em uma matriz e, em seguida, usa a expansão de parâmetro para criar a lista de .txt arquivos, substituindo .png por .txt em cada um.

Tenha em mente que isso será interrompido se você tiver tantos arquivos que nem todos podem ser passados como argumentos para a mesma invocação de touch .

    
por Tom Fenech 12.04.2017 / 15:57

Tags