Muốn tạo tệp txt cho mọi png trong thư mục


12

Tôi có kịch bản này

#!/bin/bash

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

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

Nó hoạt động, chỉ là, đối với một tệp có tên 001.png, nó tạo ra 001.png.txtthay vì 001.txt.

Làm thế nào tôi có thể sửa đổi điều này?


4
Đó là một thói quen tốt để trích dẫn các biến của bạn. Shell script là một ngôn ngữ kỳ lạ phát triển theo thời gian thay vì được thiết kế hoàn hảo từ việc di chuyển, vì vậy thật không may, một số điều gây phiền nhiễu như thế này trở nên cần thiết. Nếu không trích dẫn các biến của bạn, khoảng trắng hoặc dấu hoa thị trong nội dung biến sẽ khiến mọi thứ bị phá vỡ theo những cách kỳ lạ. Để làm cho tập lệnh của bạn mạnh mẽ hơn, luôn luôn sử dụng các biến của bạn bằng dấu ngoặc kép. Ở đây, bạn sẽ nói for filePng in "$folder"/*touch "$filePng".txt - lưu ý bạn chỉ trích dẫn chúng khi được đặt trước bởi a $.
Muzer

3
Điều này trông giống như một vấn đề XY. Tại sao bạn đang cố gắng làm điều này?
JeromeJ

Câu trả lời:


16

Bạn có thể sử dụng basenamelệnh ở đây:

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

Lưu ý bổ sung $folder/. Điều này là không cần thiết vì lệnh basename loại bỏ đường dẫn từ.


Tôi có thể đề nghị bạn trích dẫn mở rộng tham số và thay thế lệnh của bạn?
Tom Fenech

@TomFenech yeah, có lẽ là một ý tưởng tốt để trích dẫn toàn bộ chuỗi. Tôi chỉnh sửa câu trả lời của tôi.
Wayne_Yux

Tôi không chắc tại sao bạn lại xóa các trích dẫn bên trong $filePng- chúng cũng hữu ích.
Tom Fenech

1
Không, bởi vì $( )thiết lập một bối cảnh trích dẫn mới.
Tom Fenech

2
Ồ, bạn đã đúng - đã học được điều gì đó mới hôm nay ;-)
Wayne_Yux

31

Bạn có thể xóa tiện ích mở rộng hiện có bằng các tính năng mở rộng tham số của shell

${parameter%pattern}'Mẫu' được khớp với phần cuối của 'tham số'. Kết quả là giá trị mở rộng của 'tham số' với trận đấu ngắn nhất bị xóa.

Vì vậy, trong trường hợp của bạn, thay thế $filePng.txtbằng"${filePng%.png}.txt"


10

Với sự thay đổi về những gì Steeldo đã đề cập - mở rộng tham số - chúng ta có thể sử dụng thay thế chuỗi để thực hiện công việc. Ngoài ra, bạn nên trích dẫn các biến. Dưới đây là kịch bản chỉnh sửa của bạn.

#!/bin/bash

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

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

9

Nếu bạn có rất nhiều tệp để tạo thì sẽ rất đáng giá cho việc chạm vào nhiều hơn một tệp cùng một lúc, do đó bạn không cần phải xử lý một quy trình mới cho mỗi tệp đó (sẽ mất khá nhiều thời gian nếu được thực hiện nhiều lần Hàng nghìn lần).

Tùy chọn 1: thay thế mẫu + xargs

Tùy chọn này sẽ cung cấp nhiều đường dẫn cho touchlệnh cùng một lúc, thường là vài nghìn hoặc bất cứ thứ gì hệ thống có thể phù hợp trên một dòng lệnh.

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

Tùy chọn 2: mở rộng tham số + chuyển hướng đầu ra lệnh

Tùy chọn này hoàn toàn không chạy touchmà sử dụng các tính năng shell Bash / Bourne / POSIX thay vào đó không yêu cầu các quy trình phụ.

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

4

Nếu bạn tự tin rằng bạn không có tệp .pngở đâu đó ở giữa tên, thì bạn chỉ có thể sử dụng một mảng với mở rộng tham số:

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

Điều này lưu trữ tất cả các đường dẫn đến các tệp kết thúc trong .pngmột mảng và sau đó sử dụng mở rộng tham số để tạo danh sách các .txttệp, bằng cách thay thế .pngcho .txttừng tệp .

Hãy nhớ rằng điều này sẽ bị hỏng nếu bạn có quá nhiều tệp mà tất cả chúng không thể được chuyển qua làm đối số cho cùng một lệnh touch.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.