ফাইলনামে স্পেস থাকলে আমি কীভাবে ব্যবহার করব?


17

আমি অন্যান্য প্রোগ্রামগুলিতে ফাইলের নামগুলি পাইপ করতে চাই, তবে নামগুলিতে শূন্যস্থান উপস্থিত থাকাকালীন এগুলি সমস্ত শ্বাসরোধ করে।

ধরা যাক আমার কাছে একটি ফাইল আছে।

foo bar

আমি কীভাবে findসঠিক নামটি পেতে পারি ?

অবশ্যই আমি চাই:

foo\ bar

বা:

"foo bar"

সম্পাদনা : আমি যেতে চাই না xargs, আমি একটি সঠিকভাবে ফর্ম্যাট স্ট্রিং পেতে চাই findযাতে আমি ফাইলের নামের স্ট্রিংটি সরাসরি অন্য কোনও প্রোগ্রামে পাইপ করতে পারি।


5
আপনি এটি কি পাইপ করছেন? আপনি -execপতাকা সঙ্গে সচেতন find? আপনি সম্ভবত এই ত্রুটিটি দূরীভূত করতে এবং আপনার কমান্ডটিকে -execঅন্য কমান্ডগুলিতে পাইপ না করে করার দ্বারা আরও কার্যকর করতে পারেন। মাত্র আমার 0 .02
h3rrmiller

6
@ বাগ: findফাইলের নামগুলি ঠিকঠাক করে ফর্ম্যাট করে; তারা প্রতি লাইনে একটি নাম লেখা হয়। (অবশ্যই, কোনও ফাইলনেমটিতে একটি নতুন লাইন অক্ষর থাকলে এটি দ্ব্যর্থক) ।
ধনী

2
আপনি যাকে "সঠিকভাবে ফর্ম্যাটেড" বলছেন তা সত্যই "শেল দ্বারা গ্রাসের জন্য পালানো"। বেশিরভাগ ইউটিলিটিগুলি যা ফাইলের একগুচ্ছ নাম পড়তে পারে তা শেল-পলায়ন হওয়া নামকে দম বন্ধ করে দেবে, তবে বাস্তবে (বলার জন্য) findশেলের জন্য উপযুক্ত বিন্যাসে ফাইলের আউটপুট আউটপুট দেওয়ার বিকল্পটি উপলব্ধি করা বুদ্ধিমান হয়ে উঠবে । সাধারণভাবে, যদিও, -print0GNU findএক্সটেনশানটি অন্যান্য অনেক পরিস্থিতিতে (খুব) সুনির্দিষ্টভাবে কাজ করে এবং আপনার কোনও ইভেন্টে এটি ব্যবহার করতে শেখা উচিত।
ট্রিপলি

2
@ বাগ: যাইহোক, ls $(command...)তালিকাটি ফিড করে না stdin। এটি $(command...)সরাসরি কমান্ড লাইনে আউটপুট রাখে । সেক্ষেত্রে এটি শেল যা সি $IFSথেকে পড়ছে এবং আউটপুটকে কীভাবে ওয়ার্ডস্প্লিট করবে তা স্থির করার জন্য এটির বর্তমান মানটি ব্যবহার করবে । সাধারণভাবে, আপনি ব্যবহার করা ভাল xargs। আপনি একটি পারফরম্যান্স হিট লক্ষ্য করবেন না।
ধনী

2
find -printf '"%p"\n'প্রতিটি পাওয়া নামের চারপাশে ডাবল উক্তি যুক্ত করবে, তবে কোনও ফাইলের নামে কোনও ডাবল উদ্ধৃতি সঠিকভাবে উদ্ধৃত করবে না। বা পাইপ মাধ্যমে: আপনার ফাইলের নাম কোনো এমবেডেড উদ্ধৃতি চিহ্ন না থাকে, তাহলে আপনি সমস্যা উপেক্ষা করতে পারেন sed 's/"/&&/g;s/^""/"/;s/""$/"/'। যদি আপনার ফাইলের নামগুলি শেল দ্বারা পরিচালিত হয় তবে আপনার সম্ভবত ডাবল উদ্ধৃতিগুলির পরিবর্তে একক উদ্ধৃতি ব্যবহার করা উচিত, যদিও (অন্যথায় sweet$HOMEএটির মতো হয়ে যাবে sheet/home/you)। এবং এটিতে নতুন লাইনের সাথে ফাইল নামের বিরুদ্ধে এখনও খুব শক্ত নয়। আপনি কিভাবে তাদের পরিচালনা করতে চান?
ট্রিপলি

উত্তর:


18

POSIXLY:

find . -type f -exec sh -c '
  for f do
    : command "$f"
  done
' sh {} +

সঙ্গে findসমর্থন -print0এবং xargsসমর্থন -0:

find . -type f -print0 | xargs -0 <command>

-0 বিকল্পটি xargs কে ফাইলের নাম শেষ (পৃথক) করার পরিবর্তে স্থানের পরিবর্তে ASCII NUL অক্ষরটি ব্যবহার করতে বলে।

উদাহরণ:

find . -maxdepth 1 -type f -print0 | xargs -0 ls -l

কাজ করে না। আমি যখন চালাই ls $(find . -maxdepth 1 -type f -print0 | xargs -0)আমি পাই ls: cannot access ./foo: No such file or directory ls: cannot access bar: No such file or directory
বাগ

1
জ্ঞানুক যেভাবে লিখেছেন তা কি আপনি চেষ্টা করে দেখেছেন? যদি আপনি এটি নিজের উপায়ে করার জন্য জেদ করেন, তবে $(..)ডাবল-কোটগুলিতে "$(..)"
বেষ্টন

3
@ বাগ: আপনার আদেশটি ভুল। ঠিক আমি worte চেষ্টা করুন এবং এর র manpage পড়া findএবং xargs
কিউংলম

আমি দেখতে পাচ্ছি, তারপরে আবার আমি একটি ফর্ম্যাট স্ট্রিং পেতে চাই যা আমি সরাসরি পাইপ করতে পারি।
বাগ

1
@ বাগ: শুধু xargs -0 <আপনার প্রোগ্রাম> ব্যবহার করুন
কিউংএলএম

10

ব্যবহার -print0করা একটি বিকল্প, তবে সমস্ত প্রোগ্রাম নলবাইট-বিস্মৃত ডেটা স্ট্রিমগুলি ব্যবহার করে সমর্থন করে না, সুতরাং জ্নুকের উত্তর উল্লেখ করার xargsসাথে সাথে আপনাকে -0কিছু জিনিসের জন্য বিকল্পটি ব্যবহার করতে হবে ।

একটি বিকল্প findহ'ল -execবা -execdirবিকল্প ব্যবহার করা হবে । নিম্নলিখিতগুলির মধ্যে প্রথমটিতে somecommandএকবারে ফাইলের নামগুলি খাওয়ানো হবে , দ্বিতীয়টি ফাইলগুলির তালিকায় প্রসারিত হবে:

find . -type f -exec somecommand '{}' \;
find . -type f -exec somecommand '{}' +

আপনি দেখতে পাচ্ছেন যে আপনি অনেক ক্ষেত্রে গ্লোববিং ব্যবহার করা থেকে ভাল। যদি আপনার কাছে একটি আধুনিক শেল (ব্যাশ 4+, zsh, ksh) থাকে তবে আপনি globstar( **) দিয়ে পুনরাবৃত্ত গ্লোববিং পেতে পারেন । ব্যাশে, আপনাকে এটি সেট করতে হবে:

shopt -s globstar
somecommand ./**/*.txt ## feeds all *.txt files to somecommand, recursively

shopt -s globstar extglobআমার .bashrc এ আমার একটি লাইন আছে , সুতরাং এটি সর্বদা আমার জন্য সক্ষম থাকে (এবং এটি প্রসারিত গ্লোবগুলিও কার্যকর হয়)।

আপনি যদি পুনরাবৃত্তি না চান তবে কার্যত ./*.txtডিরেক্টরিতে প্রতিটি * .txt ব্যবহার করার জন্য অবশ্যই পরিবর্তে ব্যবহার করুন। findকিছু খুব দরকারী সূক্ষ্ম অনুসন্ধানের ক্ষমতা রয়েছে, এবং এটি কয়েক হাজার ফাইলের জন্য বাধ্যতামূলক (যার পরে আপনি শেলের সর্বাধিক সংখ্যক যুক্তি উপস্থাপন করবেন) তবে দিনের ব্যবহারের জন্য এটি প্রায়শই অপ্রয়োজনীয়।


আরে @ এভিলসপ এই লিপিটিতে}} কী করে?
আয়ুষমান

3

ব্যক্তিগতভাবে, আমি -execএই ধরণের সমস্যা সমাধানের জন্য অনুসন্ধান ক্রিয়াটি ব্যবহার করব use বা, যদি প্রয়োজন হয়, xargsযা সমান্তরাল সম্পাদনের অনুমতি দেয়।

যাইহোক, findফাইলনামগুলির বাশ-পঠনযোগ্য তালিকা তৈরির উপায় রয়েছে । আশ্চর্যজনকভাবে, এটি কমান্ডের বিশেষত একটি এক্সটেনশন ব্যবহার করে -execএবং :bashprintf

find ... -exec bash -c 'printf "%q " "$@"' printf {} ';'

যাইহোক, এটি শেল-পলায়নের শব্দগুলি সঠিকভাবে মুদ্রণ করবে, এটি ব্যবহারযোগ্য হবে না $(...), কারণ $(...)উদ্ধৃতিগুলি বা পলায়নের ব্যাখ্যা দেয় না। (এর পুনঃসূচনাটি $(...)শব্দ বিভাজন এবং পথের নাম প্রসার সাপেক্ষে, যদি না কোটগুলি দ্বারা ঘিরে থাকে)) সুতরাং নিম্নলিখিতটি আপনি যা চান তা করবে না:

ls $(find ... -exec bash -c 'printf "%q " "$@"' printf {} +)

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

eval "ls $(find ... -exec bash -c 'printf "%q " "$@"' printf {} +)"

(দ্রষ্টব্য যে আমি উপরের একত্ববাদ পরীক্ষা করার জন্য সত্যিকার চেষ্টা করি নি।)

তবে তারপরে আপনিও করতে পারেন:

find ... -exec ls {} +

আমি মনে করি না যে lsওপেনের ব্যবহারের পরিস্থিতিটি পর্যাপ্ত পরিমাণে ক্যাপচার করেছে, তবে এটি কেবল জল্পনা মাত্র, যেহেতু তিনি আসলে কী সম্পাদনা করতে চাইছেন তা আমাদের দেখানো হয়নি। এই সমাধানটি আসলে খুব সুন্দরভাবে কাজ করে; আমি চেষ্টা করেছি এমন মজাদার সমস্ত ফাইল নামগুলির জন্য প্রত্যাশিত আউটপুট আমি পেয়েছি (যার মধ্যে রয়েছে)touch "$(tr a-z '\001-\026' <<<'the quick brown fox jumped over the lazy dogs')"
ত্রিপলী

@ ট্রিপলি: ওপি কী করতে চায় তা আমার কোনও ধারণা নেই। উদ্ধৃত স্ট্রিংটি পাস করার evalজন্য কেবলমাত্র আসল সুবিধা হ'ল এটি আপনাকে evalএখনও পাস করতে হবে না; আপনি এটি একটি প্যারামিটারে সংরক্ষণ করতে পারেন এবং পরে এটি ব্যবহার করতে পারেন, সম্ভবত বিভিন্ন কমান্ডের সাহায্যে বেশ কয়েকবার। যাইহোক, ওপি কোনও ইঙ্গিত দেয় না যে এটি ব্যবহারের ক্ষেত্রে (এবং এটি যদি হয় তবে ফাইলের নামগুলি অ্যারেতে রাখা ভাল তবে এটি খুব
জটিলও

0
find ./  | grep " "

আপনি ফাইল এবং ডিরেক্টরি ফাঁকা স্থান পেতে হবে

find ./ -type f  | grep " " 

আপনি ফাইল ফাঁকা আছে পাবেন

find ./ -type d | grep " "

আপনি ডিরেক্টরি ফাঁকা স্থান পেতে হবে


-2
    find . -type f -name \*\  | sed -e 's/ /<thisisspace>/g'

এটি একটি আকর্ষণীয় প্রতিক্রিয়া, কিন্তু এটি এই প্রশ্নের উত্তর নয়।
স্কট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.