ফোল্ডারে লুপের জন্য তাদের নামে character n অক্ষর সহ


9

আমার কিছু ফোল্ডার রয়েছে যার সাথে \nএটির নাম রয়েছে।

উদাহরণ স্বরূপ:

$ ls
''$'\n''Test'

এটি টেস্টের নামযুক্ত কোনও ফোল্ডার এবং এর নামের আগে একটি খালি রেখা উল্লেখ করে।

সুতরাং আমি যখন এর স্ক্রিপ্টগুলি এর মূল ডিরেক্টরিতে এটি চালাই:

while IFS= read -r d; do 
    rmdir $d
done < <(find * -type d)

এটা দেখায়:

rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory

কারণ এটি দু'বার চলে, একবার \nএবং অন্যটি Test, কারণ ফোল্ডারের নামটিতে দুটি লাইন রয়েছে।

সুতরাং আমি এই সমস্যাটিকে কীভাবে সমাধান করতে পারি, স্ক্রিপ্টটি জানেন \nTestকেবল একটি ফোল্ডার?


3
আপনাকে -print0সন্ধানের নির্দেশিকা এবং -dপঠন বিকল্পটি ব্যবহার করতে হবে । দেখুন stackoverflow.com/a/40189667/7552
গ্লেন জ্যাকম্যান

1
@glennjackman দয়া করে উত্তর দিন!
মিষ্টান্ন

@glennjackman আপনার জবাবের জন্য ধন্যবাদ তবে find * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; doneকমান্ডের এই আউটপুট রয়েছে rmdir: failed to remove 'Test': No such file or directory
তারা এস ভলপ

5
আপনাকে অবশ্যই পরিবর্তনশীলটি উদ্ধৃত করতে হবে :rmdir "$file"
গ্লেন জ্যাকম্যান

1
@glennjackman উত্তর হিসাবে এটি পোস্ট করুন। এটি একটি সঠিক সমাধান এবং মন্তব্যগুলি ছাড়াও এর পক্ষে সেরা জায়গা নয় not ভোট দিন ইতিমধ্যে উহ্য :)
Sergiy Kolodyazhnyy

উত্তর:


12

আপনার কাছে কেবলমাত্র একক কমান্ড রয়েছে, তাই পতাকা কলিংয়ের findসাথে কল করার পক্ষে এটি যথেষ্ট :-execrmdir

find -depth -type d -exec rmdir {} \;

অথবা -deleteবিকল্পটি যেমনটি ব্যবহার করুন find -type d -deleteতবে এটি খালি নয় এমন ডিরেক্টরিতে কাজ করবে না। তার জন্য আপনার -emptyপতাকাও লাগবে । এছাড়াও নোট করুন, -deleteবোঝা যায় -depthযাতে এড়ানো যায়। সুতরাং অন্য একটি কার্যকর বিকল্প যা সবকিছুকে একটি প্রক্রিয়া হিসাবে রাখে:

find -type d -empty -delete

ডিরেক্টরিটি ফাঁকা না থাকলে ব্যবহার করুন rm -rf {} \;\nফাইলের নামের সাথে কেবল ডিরেক্টরিগুলি বিচ্ছিন্ন করতে আমরা বাশের এএনএসআই-সি উদ্ধৃতির $'...' সাথে -nameসংযোগ করতে পারি:

find  -type d -name $'*\n*' -empty -delete

পসিক্স-ল্য, আমরা এটি এইভাবে পরিচালনা করতে পারি:

find -depth  -type d -name "$(printf '*\n*' )" -exec rmdir {} \;

এটি উল্লেখ করার মতো যে যদি আপনার লক্ষ্যটি ডিরেক্টরিগুলি অপসারণ করা হয় তবে -deleteতা যথেষ্ট, তবে আপনি যদি ডিরেক্টরিতে কোনও কমান্ড চালাতে চান তবে -execসবচেয়ে উপযুক্ত।

আরো দেখুন


2
... rm -rf যত্ন সহকারে ব্যবহার করুন । ; P করবেন না findএকটি আছে -deleteবিকল্প BTW? এটি খালি ডিরেক্টরি মুছে ফেলে এবং খালি খালিগুলির জন্য ত্রুটি ছুঁড়ে দেয় rmdir- এটি কম ব্যয়বহুল হতে পারে।
মিষ্টান্ন

3
@ ডিজিটর এটি করে এবং আমি এটি যুক্ত করেছিলাম, তবে -deleteখালি নয় এমন ডিরেক্টরিগুলি সরাব না। অতএব, সাবধানে ব্যবহার করুনrm -rf
সের্গেই কলডিয়াজহনি

6
প্রভাবিত ফাইলগুলির তালিকাটি আসলে সঠিক কিনা এবং মুছে ফেলা উচিত নয় এমন সামগ্রী রয়েছে না তা যাচাই করার জন্য সর্বদাfind কোনও ধ্বংসাত্মক পে-লোড ছাড়াই এই জাতীয় কমান্ডগুলি শুকনোভাবে চালিত করুন (- -deleteবা অপসারণ করুন -exec whatever \;)
বাইট কমান্ডার

2
এটি Askubuntu.com তাই আমরা জিএনইউ ধরে নিতে পারি find-exec rmdir {} +এক rmdirকমান্ড লাইনে একাধিক আরগ ব্যাচ করতে ব্যবহার করুন । এবং বিটিডব্লিউ " তবে এটি খালি-ফাঁকা ডিরেক্টরিতে কাজ করে না " " এটিও প্রযোজ্য rmdir, সুতরাং এটি আসলে কোনও পার্থক্য নয় -delete। এটা থেকে পার্থক্য rm -r
পিটার কর্ডস

2
find -type d -empty -delete( -deleteবোঝানো -depth)
কেভিন

10

আপনি এর পরিবর্তে শেল গ্লোব ব্যবহার করতে পারেন find:

for d in */ ; do 
    rmdir "$d"
done

শেল গ্লোব */বর্তমান ডিরেক্টরিতে সমস্ত ফোল্ডার মেলে। এই লুপ নির্মাণটি স্বয়ংক্রিয়ভাবে সঠিক শব্দ বিভাজনের যত্ন নেয় of

মনে রাখবেন যে আপনার শেল বিকল্পগুলির উপর নির্ভর করে এটি লুকানো ফোল্ডারগুলিকে উপেক্ষা করতে পারে (নাম দিয়ে শুরু করা হয় a।)। কমান্ডটি ব্যবহার করে বর্তমান সেশনের জন্য সমস্ত ফাইলের সাথে মেলে এই আচরণটি পরিবর্তন করা যেতে পারে shopt -s dotglob

আপনার ভেরিয়েবলগুলি সর্বদা উদ্ধৃত করতে ভুলবেন না।



1
আপনি ঠিক বলেছেন @ilkkachu। গ্লোবস্টারের শেল বিকল্পটি সক্ষম করে shopt -s globstarএবং **/*/পরিবর্তে একটি গ্লোব ব্যবহার করে এটি পরিবর্তন করা যেতে পারে ।
বাইট কমান্ডার

6

এখনও অবধি লেখা দুটি উত্তরই rmdirএকবার ডিরেক্টরি অনুসারে কল করে তবে rmdirএকাধিক যুক্তি গ্রহণ করতে পারে বলে আমি ভাবছি: আরও কার্যকর উপায় নেই?

এক সহজভাবে করতে পারে

rmdir */

এবং এটি অবশ্যই সহজতম এবং কার্যকর উপায়, তবে এটি অনেক ডিরেক্টরি ক্ষেত্রে ত্রুটি ফেলতে পারে (দেখুন জিনোম-টার্মিনালে কমান্ড লাইন আর্গুমেন্টের সর্বোচ্চ দৈর্ঘ্য কত? ) যদি আপনি এই পদ্ধতির পুনরাবৃত্তভাবে কাজ করতে চান তবে globstarশেল বিকল্পটি এর সাথে সক্ষম করুন shopt -s globstarএবং এর **/*/পরিবর্তে ব্যবহার করুন */

জিএনইউ দিয়ে find(এবং যদি আমরা কেবল ব্যবহার করতে না চাই -delete), আমরা এটি করতে পারি

find -depth -type d -exec rmdir {} +

যা কমান্ড লাইনটিকে "একইভাবে xargsতার কমান্ড লাইনগুলি তৈরি করে " তে বিল্ট করে তোলে ( man find)) সাবস্টিটিউট -depthজন্য -maxdepth 1আপনি এটা recursively কাজ করতে চাই না।

একটি তৃতীয় এবং আইএমও উজ্জ্বল উপায় এই উত্তরে স্টিল্ড্রাইভার দ্বারা ব্যাখ্যা করা হয়েছে :

printf '%s\0' */ | xargs -0 rmdir

এটি printfশূন্য-বিস্মৃত আর্গুমেন্ট তালিকা তৈরি করতে শেল অন্তর্নির্মিত ব্যবহার করে , এই তালিকাটি তখন পাইপ করা হয় xargsযা rmdirপ্রায়শই প্রয়োজনীয় হিসাবে কল করে । আপনি এটি দিয়ে যাও recursively কাজ করতে পারে shopt -s globstarএবং **/*/পরিবর্তে */উপরে হিসাবে।


2
findপুনরাবৃত্তিযোগ্য, তবে ওপির লুপটি এটি নয়। সেই আচরণটি প্রতিলিপি করতে, ব্যবহার করুন find -maxdepth 1 -type d -exec rmdir {} +। ( -depthসেই ক্ষেত্রে অপ্রয়োজনীয়।) printfঅনুকরণ করার সাথে ঝরঝরে কৌশল find -print0, আমি এর আগে দেখিনি seen
পিটার কর্ডেস

1
উহু! আমি lsএবং whileলুপটি দেখেছি , আমি মিস করেছি যে তারা কোনও প্রক্রিয়া প্রতিস্থাপন থেকে লুপে findপাইপ lsনা করে কেবল কোনও কারণে এটি প্রদর্শন না করে পুনঃনির্দেশ করছে । যে find *সত্যিই সমাহিত করা হয়েছে। হ্যাঁ এটি পুনরাবৃত্ত হয়, এবং ডিরেক্টরিতে অ-ডিরেক্টরি সহ অনেক ডিরেক্টরি এন্ট্রি থাকলে ব্যর্থ হবে কারণ এটি ব্যবহার করে না */find .এটি আরও ভাল হবে, কারণ বাশের গ্লোব সম্প্রসারণের তুলনায় আইএনজি findদ্রুত stat
পিটার কর্ডস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.