কীভাবে কেবল লিনাক্স 'ফাইন্ড' দিয়ে ফাইলের নাম পাবেন?


266

আমি ডিরেক্টরিতে সমস্ত ফাইল সন্ধান করছি, তাই আমি পাথের একটি তালিকা পাই। তবে আমার কেবল ফাইলের নাম দরকার। অর্থাত্ আমি পেয়েছি ./dir1/dir2/file.txtএবং আমি পেতে চাইfile.txt

উত্তর:


359

জিএনইউতে findআপনি এর জন্য -printfপ্যারামিটার ব্যবহার করতে পারেন , যেমন:

find /dir1 -type f -printf "%f\n"

9
সুস্পষ্টভাবে উত্তর , তবে এতে বিশদ নেই।
জেসন ম্যাকক্রিরি 15


3
যখন আমি একাধিক ফাইলের ধরণ (-ও স্যুইচ) ব্যবহার করি তখন এটি আমার পক্ষে কার্যকর হয় না
উর্চিন

9
সন্ধান করুন: -প্রিন্টফ: অজানা প্রাথমিক বা অপারেটর
হোলস

@ উর্চিন কোনও কারণ নেই যতক্ষণ না আপনার পক্ষে যুক্তি সঠিক থাকে (যেমন সূচিতের -oচেয়ে কম অগ্রাধিকার রয়েছে -a, তাই আপনি প্রায়শই নিজের -oযুক্তি গোষ্ঠী করতে চান )
ইনস্টল করুন মনিকা দয়া

157

আপনার সন্ধানে যদি একটি প্রিন্টফ বিকল্প না থাকে তবে আপনি বেসনামটিও ব্যবহার করতে পারেন:

find ./dir1 -type f -exec basename {} \;

17
সেমিকোলনটি উদ্ধৃত ... {} ';'
করানো

28

ব্যবহার করুন -execdirযা স্বয়ংক্রিয়ভাবে বর্তমান ফাইলটিকে ধারণ করে {}, উদাহরণস্বরূপ:

find . -type f -execdir echo '{}' ';'

আপনি এর $PWDপরিবর্তেও ব্যবহার করতে পারেন .(কিছু সিস্টেমে এটি সামনে কোনও অতিরিক্ত বিন্দু তৈরি করে না)।

যদি আপনি এখনও অতিরিক্ত বিন্দু পেয়ে থাকেন তবে বিকল্পভাবে আপনি চালাতে পারেন:

find . -type f -execdir basename '{}' ';'

-execdir utility [argument ...] ;

-execdirপ্রাথমিক অভিন্ন -execব্যতিক্রম যে ইউটিলিটি যে ডিরেক্টরি থেকে কার্যকর করা হবে প্রাথমিক বর্তমান ফাইলটি ঝুলিতে

+পরিবর্তে ব্যবহার করা হয় ;, তারপরে {}ইউটিলিটির প্রতিটি অনুরোধের জন্য যতটা সম্ভব পথের নাম দ্বারা প্রতিস্থাপন করা হয়। অন্য কথায়, এটি সমস্ত ফাইলের নাম এক লাইনে মুদ্রণ করবে।


আমি ./filenameপরিবর্তে পাচ্ছি filename। আপনার প্রয়োজনের উপর নির্ভর করে, এটি ঠিক আছে বা নাও পারে।
ব্যবহারকারী 276648

@ user276648 এর $PWDপরিবর্তে চেষ্টা করুন .
কেনোরব

24

আপনি যদি জিএনইউ ব্যবহার করেন তবে সন্ধান করুন

find . -type f -printf "%f\n"

অথবা আপনি একটি প্রোগ্রামিং ভাষা ব্যবহার করতে পারেন যেমন রুবি (১.৯+)

$ ruby -e 'Dir["**/*"].each{|x| puts File.basename(x)}'

যদি আপনি কোনও ব্যাশ (কমপক্ষে 4) সমাধান কল্পনা করেন

shopt -s globstar
for file in **; do echo ${file##*/}; done

স্লেসকে সহায়তা করার জন্য আপনার উত্তরে আমি অনুপ্রাণিত হয়েছি: সার্ভারসফল্ট
a/

11

আপনি যদি কেবল ফাইলের বিরুদ্ধে কিছু পদক্ষেপ নিতে চান তবে ব্যবহার basenameকরা শক্ত হতে পারে।

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

find ~/clang+llvm-3.3/bin/ -type f -exec echo basename {} \; 

শুধু বেসনাম প্রতিধ্বনিত হবে /my/found/path। আমরা যদি ফাইলের নামে চালাতে চাই তবে আমরা যা চাই তা নয়।

কিন্তু আপনি তারপর xargsআউটপুট করতে পারেন । উদাহরণস্বরূপ অন্য একটি দিরের নামের উপর ভিত্তি করে একটি ডিয়ারে ফাইলগুলি হত্যা করা:

cd dirIwantToRMin;
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \; | xargs rm

প্রতিধ্বনিত করবেন না -find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \;
পাইক


1

-execএবং -execdirধীর, xargsরাজা।

$ alias f='time find /Applications -name "*.app" -type d -maxdepth 5'; \
f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l; \
f -print0 | xargs -0 basename | wc -l

     139
    0m01.17s real     0m00.20s user     0m00.93s system
     139
    0m01.16s real     0m00.20s user     0m00.92s system
     139
    0m01.05s real     0m00.17s user     0m00.85s system
     139
    0m00.93s real     0m00.17s user     0m00.85s system
     139
    0m00.88s real     0m00.12s user     0m00.75s system

xargsএর সমান্তরালতাও সাহায্য করে।

মজাদারভাবে যথেষ্ট আমি xargsছাড়া শেষ ঘটনাটি ব্যাখ্যা করতে পারি না -n1। এটি সঠিক ফলাফল দেয় এবং এটি দ্রুততম¯\_(ツ)_/¯

( basenameকেবলমাত্র 1 টি পাথ আর্গুমেন্ট নেয় তবে xargsসেগুলি পাঠিয়ে দেবে (আসলে 5000)) -n1লিনাক্স এবং ওপেনবিএসডি তে কাজ করে না, কেবলমাত্র ম্যাকোস ...)

কীভাবে -execdirসহায়তা করে তা দেখতে একটি লিনাক্স সিস্টেম থেকে কিছু বড় সংখ্যা , তবে সমান্তরালের তুলনায় এখনও অনেক ধীর xargs:

$ alias f='time find /usr/ -maxdepth 5 -type d'
$ f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l

2358
    3.63s real     0.10s user     0.41s system
2358
    1.53s real     0.05s user     0.31s system
2358
    1.30s real     0.03s user     0.21s system
2358
    0.41s real     0.03s user     0.25s system

1
আরও একটি ডেটা পয়েন্ট: দীর্ঘ দৌড়ে ওপেনবিএসডে findএটি হ'ল -execdirদ্রুততর হয়ে ওঠে কারণ নতুন প্রক্রিয়া তৈরি করা তুলনামূলক ব্যয়বহুল অপারেশন।
minusf

1

সত্যিই basenameএবং dirnameসমাধানগুলি সহজ, তবে আপনি এটিও পরীক্ষা করে দেখতে পারেন:

find . -type f | grep -oP "[^/]*$"

অথবা

find . -type f | rev | cut -d '/' -f1 | rev

অথবা

find . -type f | sed "s/.*\///"

0

অন্যরা যেমন নির্দেশ করেছে, আপনি একত্রিত করতে পারেন findএবং basename, কিন্তু ডিফল্টরূপে basenameপ্রোগ্রামটি একবারে কেবলমাত্র একটি পাথে কাজ করবে, সুতরাং প্রতিটি পাথের জন্য একবারে এক্সিকিউটেবল চালু করতে হবে (হয় ব্যবহার করে find ... -execবাfind ... | xargs -n 1 ), এটি সম্ভবত ধীর হতে পারে।

আপনি যদি -aবিকল্পটি ব্যবহার করে থাকেন basename, তবে এটি একক অনুরোধে একাধিক ফাইলের নাম গ্রহণ করতে পারে, যার অর্থ আপনি সেইগুলি xargsছাড়াই ব্যবহার করতে পারবেন -n 1, পাথগুলিকে আরও কম সংখ্যক প্রার্থনার জন্য একসাথে ভাগ করতে basename, যা আরও কার্যকর হতে হবে।

উদাহরণ:

find /dir1 -type f -print0 | xargs -0 basename -a

এখানে আমি অন্তর্ভুক্ত করেছি -print0-0ফাইল এবং ডিরেক্টরিগুলির নামের ভিতরে যে কোনও শ্বেত স্পেসের সাথে লড়াই করতে ( এবং যা একসাথে ব্যবহার করা উচিত) ।

সংস্করণ xargs basename -aএবং xargs -n1 basenameসংস্করণগুলির মধ্যে এখানে একটি সময়ের তুলনা । (মত-তুলনার মতো, এখানে রিপোর্ট করা সময়গুলি প্রাথমিক ডামি রান করার পরে, যাতে ফাইল মেটাডেটা ইতিমধ্যে I / O ক্যাশে অনুলিপি করার পরে উভয়ই সম্পন্ন হয়।) আমি আউটপুটটি পাইপ করেছি cksumউভয় ক্ষেত্রেই কেবল প্রদর্শিত হয় যে আউটপুটটি ব্যবহৃত পদ্ধতির থেকে পৃথক।

$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 basename -a | cksum'
2532163462 546663

real    0m0.063s
user    0m0.058s
sys 0m0.040s

$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 -n 1 basename | cksum' 
2532163462 546663

real    0m14.504s
user    0m12.474s
sys 0m3.109s

আপনি দেখতে পাচ্ছেন, basenameপ্রতিবারের প্রবর্তনটি এড়াতে এটি যথেষ্ট পরিমাণে দ্রুততর ।


@ মাইনুফ থেকে উত্তরটি আরও ভালভাবে পড়ার পরে, আমি দেখতে পাচ্ছি যে কোনও ম্যাকের basenameঅতিরিক্ত কোনও কমান্ড-লাইন আর্গুমেন্টের প্রয়োজন ছাড়াই একাধিক ফাইলের নাম গ্রহণ করা হবে। এখানে ব্যবহার -aলিনাক্স এ। ( basename --versionআমাকে বলে basename (GNU coreutils) 8.28।)
আলাণীবি

-3

আমি একটি সমাধান পেয়েছি (ম্যাকান্দ্রকার্ড পৃষ্ঠায়), যা কেবলমাত্র নতুন ফাইলের নাম দেয়:

ls -1tr * | tail -1

(ধন্যবাদ আর্নে হার্থার্সকে ধন্যবাদ)

আমি এটির জন্য ব্যবহার করেছি cp:

cp $(ls -1tr * | tail -1) /tmp/

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