ফাইলের নামের ফাঁকে ফাঁকে সমস্যা


8

আমি ফাইলের তালিকায় বারবার কিছু করতে চাই। প্রশ্নগুলিতে থাকা ফাইলগুলির নামে ফাঁকা স্থান রয়েছে:

david@david: ls -l
total 32
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha
-rw-rw-r-- 1 david david  0 Mai  8 11:55 haha~
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (3rd copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (4th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (5th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (6th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (7th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (another copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (copy)

এখন আমি এই ফাইলগুলির প্রতিটি স্থির করতে চাই:

david@david: echo '
for file in $(ls)
do
stat $file
done' | bash

(আমি বহু-লাইন কমান্ড লিখতে ইকো এবং একটি পাইপ ব্যবহার করি))

আমি যখন এটি করি তখন এটি সেই ফাইলগুলিতে সঠিকভাবে কাজ করে যেগুলির নামে কোনও স্থান নেই। তবে অন্য ...

stat: cannot stat ‘(another’: No such file or directory
stat: cannot stat ‘copy)’: No such file or directory

পরিবর্তন $(ls)করার জন্য "$(ls)"বা $fileকরার "$file"কাজ করে না। আমি কি করতে পারি?

সম্পাদনা:

echo '
for files in *
do
stat "$files"
done' | bash

কৌতুক করে! আমি যেমন মারামায় নতুন, আমি জিনিসগুলিকে যতটা সম্ভব সহজ করে রাখতে চাই - তাই স্পেস থেকে বাঁচার চেষ্টা করে xargsবা ব্যবহার করে বা এর সাথে সমাধান না করে read -r, যদিও তারা সমস্যার সমাধান করে।

যেমন কিছু জিজ্ঞাসা করেছেন: হ্যাঁ, এর পরিবর্তে এটি ব্যবহার stat *করা অদ্ভুত। তবে আমি কেবল লুপের জন্য একটি লুপ ব্যবহার করে ব্যাশের একটি গুচ্ছ ফাইলের নামগুলিতে একই কমান্ডটি প্রয়োগ করার একটি সাধারণ উপায় খুঁজে পেতে চেয়েছিলাম। তাই statদাঁড়াতে পারে gzip, gpgবা rm


1
এর সাথে কি হয়েছে stat *? (;-)
রমানো


আমি কেবল উদাহরণ হিসাবে স্ট্যাট ব্যবহার করি। :) আমি ls দিয়ে ফাইলের নাম সংগ্রহ করতে চাই এবং তারপরে ল্যাশের ফলাফলগুলি ব্যাশ লুপে ব্যবহার করতে চাই।
ব্যবহারকারী 258532

উত্তর:


12

এর একাধিক উক্তি জিনিসটিকে echo 'জটিল করে তুলছে।

আপনি কেবল ব্যবহার করতে পারেন:

for f in *; do stat -- "$f"; done

কিন্তু

stat -- * 

... এবং আপনি যদি ফাইলগুলি সংগ্রহ করতে চান এবং তারপরে কমান্ডটি প্রয়োগ করতে চান (কেন?) আপনি যেতে পারেন (তবে নতুন লাইনযুক্ত ফাইলের সাথে সতর্ক হন ... (1))

for f in *; do echo "$f"; done | xargs stat --

... এবং যদি আপনি খুব গোপন ফাইল প্রাপ্ত করতে ইচ্ছুক, শুধু ব্যবহার * .*নকশা হিসেবে, কিন্তু তারপর মনে রাখবেন যে .এবং ..সেট হবে

অন্যদিকে, আপনার lsআউটপুট বিশ্লেষণ করা উচিত নয়


(1) তবে আপনার যদি নতুন লাইনের সাথে ফাইল ফাইল থাকে তবে আপনি কিছুটা প্রাপ্য ... ;-)


"এবং তারপরে কমান্ডটি প্রয়োগ করুন (কেন?)" -> স্ট্যাটটি কেবল একটি স্বেচ্ছাসেবী কমান্ড হিসাবে কাজ করে, কেননা আমি চেষ্টা করছি ফাইলের নাম সহ বাশ লুপগুলি কীভাবে করা যায়। এটি জিপিজি, জিজিপ বা অন্য যে কোনও কিছু হতে পারে।
ব্যবহারকারী 258532

@ ব্যবহারকারী 258532 কমান্ড যাই হোক না কেন, সর্বদা ব্যবহার করুন for f in *; do command "$f"; done। কখনও পার্স lsকরবেন না, অবশ্যই এটি কখনই for লুপে করবেন না এবং কেন ব্যবহার করবেন echo?
টেরডন

প্রতিধ্বনি: কারণ আমি একাধিক লাইনে কমান্ডগুলি লিখতে পছন্দ করি ... :)
ব্যবহারকারী 258532

2
@ ব্যবহারকারী 258532 হু? এর জন্য আপনার প্রতিধ্বনি কেন লাগবে? শুধু এন্টার চাপুন এবং একটি নতুন লাইনে চালিয়ে যান। আপনি একটি খোলা উদ্ধৃতি দিয়ে একটি লাইন শেষ বা এক যদি do, |, &&ইত্যাদি, আপনি নতুন লাইনে চালিয়ে যেতে পারেন। হয় বা হেরডোক ব্যবহার করুন। ব্যবহার করার কোনও কারণ নেই echoএবং এটি সমস্যাও সৃষ্টি করতে পারে।
টেরডন

"সবেমাত্র এন্টার টিপুন এবং একটি নতুন লাইনে চালিয়ে যান" " সেকি। :-D এখন আমার আইকিউ আনুষ্ঠানিকভাবে 0 এর নীচে রয়েছে - আপনি জানেন, আমি বাশ এবং এই জাতীয় জিনিসগুলিতে সত্যই নতুন। তবে আমি আসলে আমার অর্থ উপার্জন করি আর (পরিসংখ্যান স্যুট এবং স্ক্রিপ্টিং ভাষা) দিয়ে।
ব্যবহারকারী 258532

6

এক পাশের নোটে: আপনি ব্যাকস্ল্যাশ অনুসরণ করে একটি স্পেস যোগ করে এবং Enterআপনি যখনই নতুন লাইনে লেখা শুরু করতে চান তখনই হিট করে একাধিক লাইনের উপরে দীর্ঘ / জটিল কমান্ডগুলি বিভক্ত করতে পারেন echo [...] | bash; ফাঁকা স্থান ফাইল ফাইলগুলির ক্ষেত্রে ভাঙ্গা $fileরোধ করতে আপনার ডাবল উদ্ধৃতিতে আবদ্ধ করা উচিত stat:

for file in $(ls); \
do \
stat "$file"; \
done

সমস্যাটি হ'ল $(ls)ফাঁকযুক্ত ফাইলের নামের তালিকায় প্রসারিত হয় এবং এটি একই সাথে ঘটবে "$(ls)"

এমনকি এই সমস্যাটি সমাধান করা, এই পদ্ধতিটি এখনও ব্যাকস্ল্যাশযুক্ত ফাইলের নাম এবং নতুন লাইনেযুক্ত ফাইলনামগুলিতে (টেরডনের দ্বারা নির্দেশিত হিসাবে) ভাঙবে।

উভয় সমস্যার জন্য একটি সমাধান নল থেকে আউটপুট হবে findএকটি থেকে whileচলমান লুপ read -rযাতে, প্রতিটি পুনরাবৃত্তির এ read -rএক লাইন সংরক্ষণ করবে find'র মধ্যে আউটপুট $file:

find . -maxdepth 1 -type f | while read -r file; do \
    stat "$file"; \
done

1
এবং লুকানো ফাইল? :)
এবি

5
এটি এখনও নতুন লাইনের সমন্বিত ফাইলের নামগুলিতে ব্যর্থ হবে। শুধু বিশ্লেষণ করবেন না ls। কখনো।
টেরডন

4
@ ব্যবহারকারী 258532 না এটি হয় না। গম্ভীরভাবে, কেবল বিশ্লেষণ করবেন নাls । আরও ভাল এবং আরও শক্তিশালী উপায় আছে। আপনি এটি পড়তেও চাইবেন : কেন * পার্স করা উচিত নয়? বিস্তারিত জানার জন্য.
টেরডন

1
এখানে সমস্যাটি নয় ls, এটি for- কীওয়ার্ডের পরে প্রদত্ত for(আইএফএস বিচ্ছিন্ন) শব্দগুলিin পুনরাবৃত্তি করে
গ্লেন জ্যাকম্যান

1
@glennjackman ভাল হ্যাঁ, এটা সমন্বয় এর forএবং lsfor f in *উদাহরণস্বরূপ, ভাল হবে।
টেরডন

3

পুরানো ভাল ব্যবহার করুন find, লুকানো ফাইল, নিউলাইন এবং স্পেসগুলির সাথে কাজ করে।

find . -print0 | xargs -I {} -0 stat {}

বা পরিবর্তে অন্য কোনও stat

find . -print0 | xargs -I {} -0 file {}
find . -print0 | xargs -I {} -0 cat {}

1

একজন আর মানুষ হিসাবে আমি ইতিমধ্যে আর-তে একটি কাজের সন্ধান পেয়েছি:

filenames <- dir(); # reads file names into an array.
                    # It works also recursively
                    # with dir(recursive=TRUE)
for (i in 1:length(filenames)) {
system(     # calls a system function
 paste(     # join stat and the file name
  "stat",
  filenames[i]
 )
)
}

আমি জানি, এটা পাগল। আমি আশা করি আউটপুট lsপার্স করা সহজ হবে ... আর স্পেসগুলি নিয়ে কাজ করতে পারে, কারণ দির () একটি উদ্ধৃত চরিত্রের মান দেয়। উদ্ধৃতিগুলির মধ্যে যে কোনও কিছু হ'ল স্পেস সহ একটি বৈধ ফাইলের নাম।


3
বিরক্ত করবেন না (তবে প্রয়াসের জন্য +1! :)। for f in *একটি নতুন লাইনে কেবল ব্যবহার করুন , এন্টার টিপুন এবং চালিয়ে যান do:, আবার stat "$f"এন্টার চাপুন, আবার doneপ্রবেশ করুন , প্রবেশ করুন। এটি একটি কমান্ড 4 লাইনে সুন্দরভাবে বিভক্ত হয় এবং কোনও ফাইলের নাম ভাঙবে না।
টেরডন

1

লুপের ক্ষেত্রে আমি হোয়াইটস্পেস ইস্যুগুলির অন্যান্য দৃষ্টান্তে চলে এসেছি, সুতরাং নিম্নলিখিত (imo আরও জোরালো) কমান্ডটি আমি সাধারণত ব্যবহার করি। এটি পাইপের মধ্যে খুব ভাল ফিট করে।

$ ls | while read line; do stat "$line"; done;

আপনি এটি একত্রিত করতে grepবা findপরিবর্তে ব্যবহার করতে পারেন :

$ find ./ -maxdepth 2 | grep '^\./[/a-z]+$' | while read line; do stat "$line"; done;

আপনার প্রথম উত্তর ব্যাকস্ল্যাশ, বা নেতৃস্থানীয় বা পিছনের স্থানগুলি ফাইল ফাইলগুলিতে ব্যর্থ। আপনার দ্বিতীয় উত্তরটি সম্পূর্ণরূপে ব্যর্থ হয় যদি না আপনি -Eবিকল্পটি যোগ করেন grep, এটি ছাড়া এটি +কোনও নিয়মিত অভিব্যক্তিতে স্বীকৃতি দেয় না। তারপরেও, এটি একটি দোল এবং এই প্রশ্নটির একটি মিস, কারণ আপনার grep স্পেস যুক্ত ফাইলের নামগুলি সরান । এটি প্রশ্নের অঙ্কগুলির উদাহরণ অনুসারে, অঙ্কগুলি (অঙ্কগুলি) এবং বিরামচিহ্ন (যেমন, প্রথম বন্ধনী) যুক্ত ফাইলের নামগুলিও সরিয়ে দেয়। এবং এটি এমনকি এমন ফাইল ফাইলগুলির উল্লেখও করে না যাতে নতুন লাইন থাকে বা -(ড্যাশ) দিয়ে শুরু হয় ।
স্কট

-1

এই উত্তরটি পার্সিংয়ের সমস্যা সমাধান করবে lsএবং ব্যাকস্পেস এবং নতুন লাইনের যত্ন নেবে

এটি ব্যবহার করে দেখুন, এটি অভ্যন্তরীণ ক্ষেত্র বিভাজক আইএফএস ব্যবহার করে আপনার সমস্যার সমাধান করবে।

IFS="\n" for f in $(ls); do   stat "$f"; done

তবে আপনি ব্যবহার করে এলএস আউটপুটকে পার্স করার প্রয়োজন ছাড়াই এটি সমাধান করতে পারেন

for f in *; do   stat "$f"; done

1
লুকানো ফাইলগুলির জন্য কাজ করে না।
এবি

2
ওপি লুকানো ফাইলগুলির জন্য জিজ্ঞাসা করেনি
মেথাক্স

1
আপনি IFSএখানে কেন সংশোধন করতে হবে তা আমি দেখতে পাচ্ছি না : শব্দটির বিভাজন রোধ করতে ভেরিয়েবলের উদ্ধৃতি দেওয়া উচিত যথেষ্ট?
স্টিল্ড্রাইভার

পার্সিংয়ের জন্য ls
মেথাক্স

ডাউনওয়েট কিসের জন্য !!!
মেথাক্স

-1

পরিবর্তে, আপনি স্থানটি প্রতিস্থাপন করে আপনার ফাইলগুলি পুনরায় নামকরণ করতে পারেন যেমন আন্ডারস্কোর হিসাবে অন্য কিছু অক্ষর, যাতে আপনি এই সমস্যা থেকে মুক্তি পান:

এটি করতে সহজেই কমান্ডটি চালান:

for file in * ; do mv "$f" "${f// /_}" ; done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.