Lệnh xuất nội dung tập tin vào thiết bị xuất chuẩn?


28

Tôi biết catcó thể làm điều này, nhưng mục đích chính của nó là để nối chứ không chỉ hiển thị nội dung.

Tôi cũng biết lessmore, nhưng tôi đang tìm kiếm thứ gì đó đơn giản ( không phải máy nhắn tin ) chỉ xuất nội dung của tệp đến thiết bị đầu cuối và nó được làm riêng cho việc này, nếu có điều đó.


1
Trên thực tế 99% số lần bạn sử dụng mèo là để hiển thị các tệp chứ không phải để nối bất cứ thứ gì.
LatinSuD

1
@LatinSuD - 100% thời gian - catnối.
mikeerv

@mikeerv: Vấn đề của bạn là gì khi thực hiện một thao tác; sử dụng ngôn ngữ bình thường sẽ ngụ ý nó được thực hiện ít nhất một lần. "In" một chuỗi trống không liên quan đến việc in bất kỳ ký tự nào; Sẽ công bằng khi nói rằng nó không in bất cứ điều gì. Bây giờ điện toán a+b+cliên quan đến việc thực hiện 2 bổ sung và điện toán akhông liên quan đến việc thêm bất cứ thứ gì. Việc thực thi tương tự cat fkhông liên quan đến việc ghép bất cứ thứ gì (mặc dù đây là điều duy nhất "nối chuỗi một tập tin" có thể có nghĩa).
Marc van Leeuwen

2
@mikeerv: Tôi không hiểu ý bạn là gì khi vào + ra. Chắc chắn catđọc một tệp và viết một tệp khác (luồng), nhưng điều đó không có nghĩa là nó được nối bất cứ thứ gì. Nếu bạn có thể có nghĩa cat flà thực sự đang làm cat - f, điều đó không đúng.
Marc van Leeuwen

1
@ bối rối00: catthực sự có nghĩa là nối ( cat file1 file2sẽ nối cả hai tệp vào thiết bị xuất chuẩn). Nhưng tác dụng phụ của nó là, khi chỉ có 1 tệp làm đối số, nó sẽ xuất ra một tệp đó thành thiết bị xuất chuẩn (bất cứ nơi nào đi, thiết bị đầu cuối của bạn hoặc được chuyển hướng đến một cái gì đó). Vì vậy, không có lệnh nào khác được tạo chỉ để xuất ra trên thiết bị xuất chuẩn, như catđã tồn tại và cho phép nó đơn giản. Do đó bạn muốn sử dụng cat.
Olivier Dulac

Câu trả lời:


37

Một trong những rõ ràng nhất là cat. Nhưng, cũng có một cái nhìn headtail. Ngoài ra còn có utillities vỏ khác để in một dòng tập tin bằng cách dòng: sed, awk, grep. Nhưng đó là để thay thế nội dung tập tin hoặc tìm kiếm bên trong tập tin.

Tôi đã thực hiện một vài thử nghiệm để ước tính cái nào là hiệu quả nhất. Tôi chạy tất cả các máng straceđể xem cái nào thực hiện các cuộc gọi hệ thống ít nhất. Tập tin của tôi có 1275 dòng.

  • awk: 1355 cuộc gọi hệ thống
  • cat: 51 cuộc gọi hệ thống
  • grep: 1337 cuộc gọi hệ thống
  • head: 93 cuộc gọi hệ thống
  • tail: 130 cuộc gọi hệ thống
  • sed: 1378 cuộc gọi hệ thống

Như bạn có thể thấy, ngay cả khi catđược thiết kế để nối các tệp, nó là cách nhanh nhất và hiệu quả nhất. sed, awkgrepin dòng tập tin bằng cách dòng, rằng tại sao họ lại có thêm rằng năm 1275 các cuộc gọi hệ thống.


8
Ý tưởng tốt để đếm các tòa nhà chọc trời!
Ngày 1 tháng

1
+1, câu trả lời chính xác hơn (về ý nghĩa của con mèo), đầy đủ hơn (lựa chọn thay thế) và nghiên cứu (tòa nhà chọc trời)
Olivier Dulac

23

Tôi biết catcó thể làm điều này, nhưng mục đích chính của nó là để nối chứ không chỉ hiển thị nội dung.

Mục đích của catchính xác là, đọc một tệp và xuất ra thiết bị xuất chuẩn.


1
Nhưng cat --helpnói "TẬP TIN FILE (hoặc) đầu vào tiêu chuẩn, với đầu ra tiêu chuẩn". Tôi không muốn kết nối bất cứ điều gì
nhầm

18
Dù bạn có tin hay không, con mèo chính xác là thứ bạn đang tìm kiếm.
Ngày 1 tháng

5
Không, @ bối rối00, đúng của Jan. Vấn đề là - thiết bị đầu cuối thiết bị xuất chuẩn - bạn thấy sao? làm readlink /dev/fd/1ví dụ - bạn sẽ nhận được tên tty của mình trong đó nếu chạy ở dấu nhắc tiêu chuẩn. Vì vậy, nối đầu vào với đầu ra là những gì bạn yêu cầu làm.
mikeerv

2
@mikeerv Vâng, tôi thấy quan điểm của bạn, tôi đoán rằng tôi đã quá cố định về ý nghĩa 'concatenate'.
bối

3
Logic là, in nội dung của một tệp chỉ là một trường hợp đặc biệt in nội dung của một hoặc nhiều tệp theo trình tự.
zwol

10

Đầu tiên, catghi vào đầu ra tiêu chuẩn, không nhất thiết phải là một thiết bị đầu cuối, ngay cả khi catđược gõ như một phần của lệnh vào một vỏ tương tác. Nếu bạn thực sự cần một cái gì đó để ghi vào thiết bị đầu cuối ngay cả khi đầu ra tiêu chuẩn được chuyển hướng, điều đó không dễ dàng (bạn cần chỉ định thiết bị đầu cuối nào, và thậm chí có thể không có một nếu lệnh được thực thi từ tập lệnh), mặc dù một lệnh (ab) có thể sử dụng đầu ra lỗi tiêu chuẩn nếu lệnh chỉ là một phần của đường ống. Nhưng vì bạn đã chỉ ra rằng catthực sự làm công việc đó, tôi cho rằng bạn không hỏi về tình huống như vậy.

Nếu mục đích của bạn là gửi những gì được ghi vào đầu ra tiêu chuẩn vào một đường ống, thì việc sử dụng catsẽ đủ điều kiện nhận Giải thưởng Sử dụng Mèo vô dụng , vì cat file | pipeline(trong đó pipelineviết tắt của bất kỳ đường ống nào) có thể được thực hiện hiệu quả hơn <file pipeline. Nhưng một lần nữa, từ cách diễn đạt của bạn, tôi suy luận rằng đây không phải là ý định của bạn.

Vì vậy, nó không phải là quá rõ ràng những gì bạn đang lo lắng. Nếu bạn thấy catquá dài để nhập, bạn có thể xác định bí danh một hoặc hai ký tự (vẫn còn một vài tên như vậy vẫn chưa được sử dụng trong Unix tiêu chuẩn). Tuy nhiên, nếu bạn lo lắng rằng việc catchi tiêu chu kỳ vô ích, bạn không nên.

Nếu có một chương trình nullkhông có đối số và chỉ sao chép đầu vào tiêu chuẩn thành đầu ra tiêu chuẩn (đối tượng trung tính cho đường ống), bạn có thể làm những gì bạn muốn với <file null. Không có chương trình nào như vậy, mặc dù nó sẽ dễ viết (chương trình C chỉ với mainchức năng một dòng có thể thực hiện công việc), nhưng gọi catmà không có đối số (hoặc cat -nếu bạn muốn rõ ràng) sẽ làm điều đó.

Nếu có một nocatchương trình lấy chính xác một đối số tên tệp, cố gắng mở tệp, khiếu nại nếu không thể, và nếu không thì tiến hành sao chép từ tệp sang đầu ra tiêu chuẩn, thì đó sẽ chỉ là những gì bạn đang yêu cầu. Nó chỉ khó viết hơn một chút so với null, công việc chính là mở tệp, kiểm tra và có thể phàn nàn (nếu bạn tỉ mỉ, bạn cũng có thể muốn bao gồm một bài kiểm tra có một đối số và khiếu nại khác). Nhưng một lần nữa cat, bây giờ được cung cấp với một đối số duy nhất, thực hiện điều đó, do đó không cần bất kỳ nocatchương trình nào .

Một khi bạn đã thành công trong việc viết nocatchương trình, tại sao chỉ dừng lại ở một đối số? Việc gói mã vào một vòng lặp for(;*argp!=NULL;++argp)thực sự không có chút nỗ lực nào, thêm nhiều nhất một vài hướng dẫn máy vào nhị phân và tránh phải phàn nàn về một số lượng đối số sai (bỏ qua nhiều hướng dẫn khác). Voilà một phiên bản nguyên thủy của catcác tập tin nối. (Thành thật mà nói, bạn cần phải tinh chỉnh nó một chút để không có đối số, nó hoạt động như null.)

Tất nhiên trong catchương trình thực tế , họ đã thêm một vài tiếng chuông và còi, bởi vì họ luôn luôn làm như vậy. Nhưng điều cốt lõi là khía cạnh "kết hợp" của catchi phí thực sự không có nỗ lực nào cả, cho cả lập trình viên cũng như cho máy thực hiện nó. Thực tế là catbao gồm nullnocatgiải thích sự không tồn tại của các chương trình như vậy. Tránh sử dụng catvới một đối số duy nhất nếu kết quả đi vào một đường ống, nhưng nếu nó chỉ được sử dụng để hiển thị nội dung tệp trên thiết bị đầu cuối, ngay cả trang tôi liên kết để thừa nhận rằng đây là cách sử dụng hữu ích cat, vì vậy đừng ngần ngại.


Bạn có thể kiểm tra catthực sự được thực hiện bằng một vòng lặp đơn giản xung quanh nocatchức năng giả định, bằng cách gọi catvới một số tên tệp trong đó một tên không hợp lệ, không ở vị trí đầu tiên: thay vì phàn nàn ngay lập tức rằng tệp này không tồn tại, cattrước tiên hãy bỏ qua các tệp hợp lệ và sau đó phàn nàn về tệp không hợp lệ (ít nhất đó là cách con mèo của tôi cư xử).


7

Đang zshcố gắng

<file

Tôi tin rằng đó là cách ngắn nhất để in một tập tin. Nó sử dụng 'hidden' cat(hoặc morenếu stdout là thiết bị đầu cuối), nhưng lệnh được sử dụng để in được điều khiển bởi READNULLCMDbiến mà bạn có thể ghi đè trực tiếp bằng tên lệnh hoặc thậm chí bởi một số chức năng. Ví dụ để in các tệp có đánh số dòng:

numcat() { nl -s'> ' -w2 - }
READNULLCMD=numcat
<file

5

POSIX định nghĩa mèo là:

TÊN

cat - concatenate và in các tập tin

TÓM TẮC

mèo [-u] [tập tin ...]

SỰ MIÊU TẢ

Tiện ích mèo sẽ đọc các tệp theo trình tự và sẽ ghi nội dung của chúng vào đầu ra tiêu chuẩn theo cùng một trình tự.

Vì vậy, tôi nghĩ concatenate ở đây có nghĩa là đọc các tệp theo trình tự .


5

Tôi biết đây là một câu hỏi quá khứ. Về mặt kỹ thuật, vì in nội dung của tệp thành stdoutmột hình thức ghép, catlà phù hợp về mặt ngữ nghĩa. Đừng quên rằng printfvề mặt ngữ nghĩa nhằm định dạng và in dữ liệu. Bash cũng cung cấp cú pháp để chuyển hướng đầu vào và đầu ra từ các tệp. Một sự kết hợp của những thứ này có thể tạo ra điều này:

printf '%s' "$(<file.txt)"

4
Ngoài việc đặc biệt là đường vòng, lệnh được hiển thị không tương đương cat file.txt, vì nó sẽ xóa bất kỳ dòng mới nào ( $(...)thực hiện điều này).
Marc van Leeuwen

+1, bắt đẹp. Không biết rằng.
James M. Lay

3

Sử dụng bashnội trang và tránh tạo quy trình con:

{ while IFS='' read -rd '' _bcat_; do printf '%s\0' "${_bcat_}"; done; printf '%s' "${_bcat_}"; unset _bcat_; } <'/path/to/file'

IFSsẽ chỉ được áp dụng cho readlệnh, vì vậy đừng lo lắng về IFSnhững thay đổi toàn cầu của bạn .

Vòng lặp cần thiết để xử lý các ký tự null (nhờ Stéphane Chazelas).

Cách này không phù hợp với các tệp lớn vì nội dung tệp đọc trước biến (vì vậy bộ nhớ) trước. BTW Tôi đã thử in tệp văn bản 39M theo cách này và mức sử dụng bộ nhớ bash không vượt quá 5M, vì vậy không chắc chắn về trường hợp này.

Nó cũng rất chậm và CPU không hiệu quả: với cùng một tệp 39M, phải mất 3 phút với 100% sử dụng lõi đơn.

Đối với các tệp lớn hoặc nhị phân tốt hơn để sử dụng cat '/path/to/file'hoặc thậm chí dd if='/path/to/file' bs=1Mnếu có thể.


1
Xem thêm pv -qtrên Linux có thể sử dụng splice()cái nào cho một số loại stdin / stdout sẽ cải thiện hiệu suất.
Stéphane Chazelas

1

Chỉ là một cuộc biểu tình, bạn có thể làm

cp foo /dev/stdout
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.