Klasördeki her png için txt dosyaları yapmak istiyorum


12

Bu senaryoya sahibim

#!/bin/bash

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

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

Bu adında bir dosya için sadece, yani işleri 001.png, oluşturduğu 001.png.txtyerine 001.txt.

Bunu nasıl değiştirebilirim?


4
Değişkenlerinizi alıntılamak iyi bir alışkanlıktır. Kabuk betiği, hareket halindeyken mükemmel bir şekilde tasarlanmak yerine zamanla gelişen garip bir dildir, bu yüzden maalesef bunun gibi can sıkıcı şeyler gerekli hale gelir. Değişkenlerinizi alıntılamaksızın, değişken içeriğindeki boşluk veya yıldız işaretleri işlerin garip yollarla kırılmasına neden olur. Komut dosyalarınızı daha sağlam hale getirmek için değişkenlerinizin kullanımını her zaman çift tırnak içine alın. Burada şunu söylerdiniz for filePng in "$folder"/*ve touch "$filePng".txt - yalnızca a $.
Muzer

3
Bu bir XY problemine benziyor… Bunu neden yapmaya çalışıyorsunuz?
JeromeJ

Yanıtlar:


16

basenameKomutu burada kullanabilirsiniz :

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

Ek not $folder/. Basename komutu yolu kaldırdığı için bu gerekli değildir.


Parametre genişletme ve komut değiştirme işlemlerinizi alıntılamanızı önerebilir miyim?
Tom Fenech

@TFFenech evet, muhtemelen tüm dizeyi alıntılamak için iyi bir fikir. Cevabımı düzenledim.
Wayne_Yux

İç tırnakları neden kaldırdığınızdan emin değilim $filePng- onlar da faydalıydı.
Tom Fenech

1
Hayır, çünkü $( )yeni bir alıntı bağlamı oluşturur.
Tom Fenech

2
Oh, haklısın - bugün yeni bir şey öğrendim ;-)
Wayne_Yux

31

Kabuğun parametre genişletme özelliklerini kullanarak mevcut uzantıyı kaldırabilirsiniz

${parameter%pattern}'Desen', 'parametre' sonuna eşleştirilir. Sonuç, en kısa eşleşme silinmiş olarak 'parametre'nin genişletilmiş değeridir.

Yani senin durumunda, yerini $filePng.txtile"${filePng%.png}.txt"


10

Daha önce bahsedilen steeldriver'ın - parametre genişletme - varyasyonuyla, işi yapmak için dize değiştirme işlemini kullanabiliriz. Buna ek olarak, değişkenleri belirtmelisiniz. Aşağıda düzenlenen komut dosyanız var.

#!/bin/bash

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

for filePng in "$folder"/*
do
    touch "${filePng/.png/.txt}"
done

9

Eğer varsa çok dosyalarının gerçekleştirdiğiniz katına eğer biraz zaman alacaktır bunların her biri için yeni bir süreç (çatal gerekmez böylece, bir seferde birden fazla dosya “dokunma” için faydalı olacaktır oluşturmak için bin kez).

Seçenek 1: Kalıp değiştirme + xargs

Bu seçenek touch, bir kerede komuta birden fazla yol sağlar , genellikle birkaç bin veya sistemin tek bir komut satırına sığabileceği her şey.

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

2.Seçenek: Parametre genişletme + komut çıkışı yeniden yönlendirmesi

Bu seçenek hiç çalışmaz touchancak bunun yerine alt işlemler gerektirmeyen Bash / Bourne / POSIX kabuk özelliklerini kullanır.

for f in "$folder"/*.png; do
    : >> "${f%.png}.txt"
done

4

.pngAdın ortasında bir yerde dosya bulunmadığından eminseniz, parametre genişletmeli bir dizi kullanabilirsiniz:

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

Bu depolar her biten dosyalara yolları .pngdaha sonra bir dizi ve bir liste oluşturmak için bir parametre genişleme kullanır .txtikame edilerek, dosyalar .pngiçin .txther biri.

Aynı çağrının argümanları olarak argüman olarak iletilemeyecek kadar çok dosyanız varsa bunun kırılacağını unutmayın touch.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.