কম্পিউটার টিউটোরিয়াল

বড় ফাইলসিস্টেমে ফাইল বা ডিরেক্টরি সহজে তালিকাভুক্ত করার ব্যাশ স্ক্রিপ্ট

আপনি কখনো কি একটি ডিরেক্টরির সব ফাইল তালিকাভুক্ত করতে চেয়েছেন, কিন্তু শুধু ফাইলগুলো, আর কিছু নয়? কি শুধু ডিরেক্টরি গুলো? যদি হ্যাঁ, তবে নিচের স্ক্রিপ্টটি, যা GPLv3-এর অধীনে ওপেন সোর্স, আপনি যা খুঁজছেন সেটি হতে পারে।

অবশ্যই, আপনি find কমান্ড ব্যবহার করতে পারেন:

find . -maxdepth 1 -type f -print

কিন্তু এটি টাইপ করা কষ্টসাধ্য, আউটপুট অনফ্রেন্ডলি, এবং ls কমান্ডের কিছু রিফাইনমেন্ট নেই। আপনি ls এবং grep কম্বাইন করেও একই ফলাফল পেতে পারেন:

ls -F . | grep -v /

কিন্তু আবারও, এটি ক্লাঙ্কি। এই স্ক্রিপ্টটি একটি সহজ বিকল্প প্রদান করে।

ব্যবহার

স্ক্রিপ্টটি চারটি মূল ফাংশন প্রদান করে, যা নির্ভর করে আপনি কোন নামে কল করছেন: lsf ফাইল তালিকাভুক্ত করে, lsd ডিরেক্টরি তালিকাভুক্ত করে, lsx এক্সিকিউটেবল তালিকাভুক্ত করে, এবং lsl লিংক তালিকাভুক্ত করে।

স্ক্রিপ্টের একাধিক কপি ইনস্টল করার প্রয়োজন নেই, সিমবলিক লিংক কাজ করে। এটি স্পেস বাঁচায় এবং স্ক্রিপ্ট আপডেট করা সহজ করে।

স্ক্রিপ্টটি find কমান্ড ব্যবহার করে সার্চ করার জন্য, এবং তারপর প্রতিটি ফাউন্ড আইটেমে ls রান করে। এর চমৎকার দিক হলো স্ক্রিপ্টে দिये गये যেকোনো আর্গুমেন্ট ls কমান্ডে পাস হয়। তাই, উদাহরণস্বরূপ, এটি সব ফাইল তালিকাভুক্ত করে, ডট দিয়ে শুরু হওয়া ফাইলগুলিও:

lsf -a

লং ফরম্যাটে ডিরেক্টরি তালিকাভুক্ত করতে, lsd কমান্ড ব্যবহার করুন:

lsd -l

আপনি একাধিক আর্গুমেন্ট, এবং ফাইল ও ডিরেক্টরি পাথও দিতে পারেন।

এটি বর্তমান ডিরেক্টরির প্যারেন্ট ডিরেক্টরির এবং /usr/bin ডিরেক্টরির সব ফাইলের একটি লং ক্লাসিফাইড তালিকা প্রদান করে:

lsf -F -l .. /usr/bin

একটি জিনিস যা স্ক্রিপ্টটি বর্তমানে হ্যান্ডেল করে না, সেটি হলো রিকারশন। এই কমান্ড শুধু বর্তমান ডিরেক্টরির ফাইলগুলো তালিকাভুক্ত করে।

lsf -R

স্ক্রিপ্টটি কোনো সাবডিরেক্টরির মধ্যে নেমে না। এটি একদিন ফিক্স করা হয়।

আন্তরিক কাজকর্ম

স্ক্রিপ্টটি টপ-ডাউন ফ্যাশনে লেখা হয়েছে প্রাথমিক ফাংশনগুলো স্ক্রিপ্টের শুরুতে এবং মূল কাজ শেষে পারফর্ম করা হয়েছে। স্ক্রিপ্টে শুধু দুটি ফাংশন আছে যা প্রকৃতপক্ষে গুরুত্বপূর্ণ। parse_args() ফাংশন কমান্ড লাইন পার্স করে, অপশনগুলো পথের নাম থেকে আলাদা করে, এবং ls কমান্ড-লাইন অপশন থেকে স্ক্রিপ্ট-স্পেসিফিক অপশনগুলো আলাদা করে।

list_things_in_dir() ফাংশন একটি ডিরেক্টরি নাম আর্গুমেন্ট হিসেবে নেয় এবং সেটিতে find কমান্ড রান করে। প্রতিটি ফাউন্ড আইটেম ls কমান্ডে পাস করা হয় ডিসপ্লের জন্য।

উপসংহার

এটি একটি সাধারণ ফাংশন সম্পন্ন করার একটি সহজ স্ক্রিপ্ট। এটি একটি টাইম সেভার এবং বড় ফাইলসিস্টেমের সাথে কাজ করার সময় আশ্চর্য করে উপযোগী হতে পারে।

স্ক্রিপ্ট

#!/bin/bash

# স্ক্রিপ্টের জন্য তালিকাভুক্ত করা:
# ডিরেক্টরি (যদি "lsd" নামে ডাকা হয়)
# ফাইল (যদি "lsf" নামে ডাকা হয়)
# লিংক (যদি "lsl" নামে ডাকা হয়)
# বা এক্সিকিউটেবল (যদি "lsx" নামে ডাকা হয়)
# কিন্তু অন্য যেকোনো টাইপের ফাইলসিস্টেম অবজেক্ট নয়।
# FIXME: lsp যোগ করুন (পাইপ তালিকাভুক্ত করুন)
#
# ব্যবহার:
# <command_name> [ls কমান্ডের জন্য বৈধ সুইচ] [dirname...]
#
# স্পেস সহ নাম এবং হাইফেন দিয়ে শুরু হওয়া নামের সাথে কাজ করে।
#
# Ник ক্লিফটন দ্বারা তৈরি।
# ভার্সন 1.4
# Copyright (c) 2006, 2007 Red Hat.
#
# এটি মুক্ত সফটওয়্যার; আপনি এটি পুনর্বিতরণ এবং/অথবা মডিফাই করতে পারেন
# GNU জেনারেল পাবলিক লাইসেন্সের শর্তাবলীর অধীনে যা প্রকাশিত
# ফ্রি সফটওয়্যার ফাউন্ডেশন দ্বারা; হয় সংস্করণ ৩, অথবা (আপনার
# অপশনে) যেকোনো পরবর্তী সংস্করণ।

# এটি বিতরণ করা হচ্ছে আশা করা হচ্ছে এটি উপযোগী হবে, কিন্তু
# কোনো ওয়ারেন্টি ছাড়া; ব্যবসায়িক যোগ্যতা বা নির্দিষ্ট উদ্দেশ্যের জন্য
# উপযোগিতার নিহিত ওয়ারেন্টি ছাড়াই। GNU জেনারেল পাবলিক লাইসেন্সের জন্য
# আরও বিবরণ দেখুন।

# ToDo:
# রিকারশন হ্যান্ডেল করুন, যেমন: lsl -R
# আর্গুমেন্ট নেওয়া সুইচ হ্যান্ডেল করুন, যেমন --block-size
# --almost-all, --ignore-backups, --format এবং --ignore হ্যান্ডেল করুন

main ()
{
init

parse_args ${1+"$@"}

list_objects

exit 0
}

report ()
{
echo $prog": " ${1+"$@"}
}

fail ()
{
report " Internal error: " ${1+"$@"}
exit 1
}

# গ্লোবাল ভেরিয়েবল инициализация করুন।
init ()
{
# ডিফল্টভাবে বর্তমান ডিরেক্টরির জিনিসগুলো তালিকাভুক্ত করুন।
dirs[0]=".";

# num_dirs হলো তালিকাভুক্ত করার ডিরেক্টরির সংখ্যা মাইনাস वन।
# এটি কারণ আমরা dirs[] অ্যারে থেকে শূন্য থেকে ইনডেক্স করছি।
num_dirs=0;

# ডিফল্টভাবে ডট দিয়ে শুরু হওয়া জিনিসগুলো ইগনোর করুন।
no_dots=1

# নোট - গ্লোবাল ভেরিয়েবল 'type' এবং 'opts' ইনিশিয়ালাইজ হয়
# parse_args ফাংশনে।
}

# আমাদের কমান্ড লাইন পার্স করুন
parse_args ()
{
local no_more_args

no_more_args=0 ;

prog=`basename $0` ;

# সিদ্ধান্ত নিন আমরা ফাইল না ডিরেক্টরি তালিকাভুক্ত করব।
case $prog in
lsf | lsf.sh)
type=f
opts="";
;;
lsd | lsd.sh)
type=d
# ডিরেক্টরি তালিকাভুক্ত করার সময় "ls"-এর -d সুইচ অনুমান করা হয়।
opts="-d";
;;
lsl | lsl.sh)
type=l
# তালিকাভুক্ত লিংকগুলো ফলো না হওয়া নিশ্চিত করতে -d ব্যবহার করুন।
opts="-d";
;;
lsx | lsx.sh)
type=f
find_extras="-perm /111"
;;
*)
fail "Unrecognised program name: '$prog', expected either 'lsd', 'lsf', 'lsl' or 'lsx'"
;;
esac

# ls-এর জন্য যেকোনো অতিরিক্ত কমান্ড লাইন সুইচ লোকেট করুন এবং সেগুলো জমা করুন।
# একইভাবে নন-সুইচগুলো ডিরেক্টরি তালিকায় জমা করুন।
while [ $# -gt 0 ]
do
case "$1" in
# FIXME: আর্গুমেন্ট নেওয়া সুইচ হ্যান্ডেল করুন, যেমন --block-size
# FIXME: সঠিকভাবে --almost-all, --ignore-backups, --format
# FIXME: এবং --ignore হ্যান্ডেল করুন
# FIXME: সঠিকভাবে --recursive হ্যান্ডেল করুন
-a | -A | --all | --almost-all)
no_dots=0;
;;
--version)
report "version 1.2"
exit 0
;;
--help)
case $type in
d) report "a version of 'ls' that lists only directories" ;;
l) report "a version of 'ls' that lists only links" ;;
f) if [ "x$find_extras" = "x" ] ; then
report "a version of 'ls' that lists only files" ;
else
report "a version of 'ls' that lists only executables";
fi ;;
esac
exit 0
;;
--)
# একটি সুইচ যা বলে যে কমান্ড লাইনে আরও সব আইটেম
# আর্গুমেন্ট, সুইচ নয়।
no_more_args=1 ;
;;
-*)
if [ "x$no_more_args" = "x1" ] ;
then
dirs[$num_dirs]="$1";
let "num_dirs++"
else
# একটি সুইচ চেক করুন যা শুধু একটি ড্যাশ ব্যবহার করে, ডাবল
# ড্যাশ নয়। এটি আসলে একাধিক সুইচ এক শব্দে কম্বাইন করা হতে পারে,
# যেমন "lsd -alF"। এই কেসে, -a সুইচের জন্য স্ক্যান করুন।
# XXX: FIXME: =~ এর ব্যবহার ব্যাশ v3.0+ বাধ্য করে।
if [[ "x${1:1:1}" != "x-" && "x$1" =~ "x-.*a.*" ]] ;
then
no_dots=0;
fi
opts="$opts $1";
fi
;;
*)
dirs[$num_dirs]="$1";
let "num_dirs++"
;;
esac
shift
done

# মনে রাখবেন আমরা শূন্য থেকে কাউন্ট করছি এক নয়।
if [ $num_dirs -gt 0 ] ;
then
let "num_dirs--"
fi
}

list_things_in_dir ()
{
local dir

# প্যারানোইয়া চেক - ব্যবহারকারী কখনো এইরকম কিছু দেখার দরকার নেই।
if test "x$1" = "x" ;
then
fail "list_things_in_dir called without an argument"
fi

if test "x$2" != "x" ;
then
fail "list_things_in_dir called with too many arguments"
fi

# $dir অ্যাক্সেস করার সময় কোটেশন ব্যবহার করুন যাতে
# ডিরেক্টরি নামের যেকোনো স্পেস সংরক্ষিত থাকে।
dir="${dirs[$1]}";

# ড্যাশ দিয়ে শুরু হওয়া ডিরেক্টরি নাম ক্যাচ করুন - তারা
# pushd-কে বিভ্রান্ত করে।
if test "x${dir:0:1}" = "x-" ;
then
dir="./$dir"
fi

if [ -d "$dir" ]
then
if [ $num_dirs -gt 0 ]
then
echo " $dir:"
fi

# ডিরেক্টরি নামটি find-এ পাস করার পরিবর্তে pushd ব্যবহার করুন যাতে
# যে নামগুলো find xargs-এ পাস করে সেগুলোর সাথে কোনো পাথ প্রিপেন্ডেড থাকে না।
pushd "$dir" > /dev/null
if [ $no_dots -ne 0 ] ; then
find . -maxdepth 1 -type $type $find_extras -not -name ".*" -printf "%f\000" \
| xargs --null --no-run-if-empty ls $opts -- ;
else
find . -maxdepth 1 -type $type $find_extras -printf "%f\000" \
| xargs --null --no-run-if-empty ls $opts -- ;
fi
popd > /dev/null
else
report "directory '$dir' could not be found"
fi
}

list_objects ()
{
local i

i=0;
while [ $i -le $num_dirs ]
do
list_things_in_dir i
let "i++"
done
}

# main আহ্বান করুন
main ${1+"$@"}
  1. পहेলি-ভিত্তিক শিক্ষণ দ্বারা ব্যাশ দক্ষতা 습득 করুন

  2. লিনাক্সে স্টারগেজিংয়ের সময় রাত্রি দৃষ্টি রক্ষার জন্য ব্যাশ স্ক্রিপ্ট

  3. সহজে ঘরে ডাবল-সাইডেড ডকুমেন্ট প্রিন্ট করুন একটি সাধারণ ব্যাশ স্ক্রিপ্ট দিয়ে

  4. ব্যাশ স্ক্রিপ্টিং মাস্টার করুন: ৫টি রিয়েল-ওয়ার্ল্ড উদাহরণসহ প্র্যাক্টিক্যাল ইন্ট্রোডাকশন