ব্যাশ স্ক্রিপ্ট ব্যবহার করে ফাইলের নামগুলিতে শূন্যস্থান কীভাবে প্রতিস্থাপন করা যায়


264

প্রদত্ত রুট ডিরেক্টরি থেকে শুরু হওয়া ফাইল এবং ডিরেক্টরি নামগুলির আন্ডারস্কোরগুলির সাথে স্পেসগুলি পুনরাবৃত্তভাবে প্রতিস্থাপনের জন্য কেউ নিরাপদ সমাধানের পরামর্শ দিতে পারেন? উদাহরণ স্বরূপ:

$ tree
.
|-- a dir
|   `-- file with spaces.txt
`-- b dir
    |-- another file with spaces.txt
    `-- yet another file with spaces.pdf

হয়ে:

$ tree
.
|-- a_dir
|   `-- file_with_spaces.txt
`-- b_dir
    |-- another_file_with_spaces.txt
    `-- yet_another_file_with_spaces.pdf

9
যদি একটি ডিরেক্টরি foo barবলা foo_barহয় এবং একই ডিরেক্টরিতে অন্য একটি ফাইল বলা হয় তবে আপনি কী হতে চান ?
মার্ক বায়ার্স

ভাল প্রশ্ন. আমি বিদ্যমান ফাইলগুলি ওভাররাইট করতে বা কোনও ডেটা হারাতে চাই না। এটি এটিকে অপরিবর্তিত রাখা উচিত .. আদর্শভাবে একটি সতর্কতা প্রিন্ট করা উচিত তবে এটি সম্ভবত খুব বেশি জিজ্ঞাসা করছে।
আর্মান্দিনো

উত্তর:


311

rename(ওরফে prename) ব্যবহার করুন যা পার্ল স্ক্রিপ্ট যা আপনার সিস্টেমে ইতিমধ্যে থাকতে পারে। এটি দুটি পদক্ষেপে করুন:

find -name "* *" -type d | rename 's/ /_/g'    # do the directories first
find -name "* *" -type f | rename 's/ /_/g'

উপর ভিত্তি করে ইয়ুর্গেন এর উত্তর এবং "সংশোধনের 1.5 1998/12/18 16:16:31 rmb1" এর সংস্করণ ব্যবহার একটি একক বাউন্ড ফাইল ও ডিরেক্টরিগুলি একাধিক স্তরের হ্যান্ডেল করতে সক্ষম /usr/bin/rename(ক পার্ল স্ক্রিপ্ট):

find /tmp/ -depth -name "* *" -execdir rename 's/ /_/g' "{}" \;

5
দুটি পদক্ষেপের প্রয়োজন নেই: গভীরতা-প্রথম অনুসন্ধানটি ব্যবহার করুন: দির-
ডেপথ খুঁজুন

3
ওহ, আমি শুধু পড়েছি renameর manpage (আমি টুল জানেন না) এবং আমি মনে করি আপনি পরিবর্তন করে আপনার কোড অপটিমাইজ করতে পারেন s/ /_/gথেকে y/ /_/;-)
হ্যাকার - মাইকেল Krelin

1
অবশ্যই আপনি এটি থেকে একটি পারফরম্যান্স উত্সাহ পেতে যাচ্ছেন না। এটি সঠিক সরঞ্জামটি ব্যবহার সম্পর্কে আরও বেশি। এবং এই পুরো প্রশ্নটি কমবেশি মাইক্রো অনুকূলকরণ সম্পর্কে। মজা না, সব পরে? ;-)
মাইকেল ক্রেলিন - হ্যাকার

14
আপনি যদি এটি ওএস এক্সে চালাচ্ছেন তবে আপনার প্রয়োজন হবেbrew install rename

7
এটি সেন্টোস on-তে কাজ করে না, কারণ নাম পরিবর্তনের আদেশটি সম্পূর্ণ আলাদা (এটি একটি বাইনারি, পার্ল স্ক্রিপ্ট নয়), এবং এটি স্টিডিনের ডেটা গ্রহণ করে না।
CpnCrunch

357

আমি ব্যবহার করি:

for f in *\ *; do mv "$f" "${f// /_}"; done

যদিও এটি পুনরাবৃত্ত হয় না, এটি বেশ দ্রুত এবং সহজ। আমি নিশ্চিত যে এখানে কেউ এটি পুনরাবৃত্ত হওয়ার জন্য আপডেট করতে পারে।

${f// /_}অংশ সরবরাহকৃত স্ট্রিং সঙ্গে একটি প্যারামিটার মধ্যে একটি প্যাটার্ন প্রতিস্থাপন ব্যাশ এর প্যারামিটার সম্প্রসারণ প্রক্রিয়া ব্যবহার করে। প্রাসঙ্গিক বাক্য গঠন ${parameter/pattern/string}। দেখুন: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html বা http://wiki.bash-hackers.org/syntax/pe


9
সহজ এবং ম্যাক কাজ। (ম্যাকের কাছে এটি নেই rename, এবং এটি
মেশানো

6
দুর্দান্ত উত্তর আমি for d in *\ *; do mv "$d" "${d// /}"; doneস্কোর নন ব্যবহার করেছি
ইউন লি

1
'ফাইন্ড-নেম' উত্তরটির বিপরীতে, এটি আমার ওএস এক্সে কাজ করেছে! ধন্যবাদ জনাব!
জুলিও ফারম্যান

1
রেফারেন্সের জন্য, এটি সহজেই ব্যবহার এবং এর জন্য ব্যাশে পুনরাবৃত্ত হয়ে উঠতে পারে । যেহেতু বিকল্প, ব্যাশ থেকে অভ্যন্তরীণ ব্যবহারের জন্য কমান্ড একটি সাধারণ লিনাক্স টুল এবং ব্যাশ অংশ। shopt -s globstarfor f in **/*\ *; do ...globstarrename
ঘোটি

2
${f// /_}অনুসন্ধান এবং প্রতিস্থাপনের জন্য একটি ব্যাশ ভেরিয়েবল প্রসারণ । - প্রতিটি ফাইলের জন্য একটি স্থান থাকা লুপ থেকে পরিবর্তনশীল । - প্রথম অর্থ "সমস্ত প্রতিস্থাপন করুন" (প্রথম ঘটনায় থামবেন না)। - তারপরে `/ _` এর অর্থ" আন্ডারস্কোর দিয়ে স্থান প্রতিস্থাপন করুন "ffor//
এরি

101
find . -depth -name '* *' \
| while IFS= read -r f ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr ' ' _)" ; done

প্রথমে এটি পেতে ব্যর্থ হয়েছে, কারণ আমি ডিরেক্টরিগুলির কথা ভাবি নি।


1
একটি যাদুমন্ত্র মত কাজ করে. ধন্যবাদ মাইকেল।
আরমান্ডিনো

ডেনিস, ভাল ক্যাচ, সহজেই IFS=''সামনে রেখে স্থির করা read। এছাড়াও, আমি অন্যান্য মন্তব্যে যা বলতে পারি তার জন্য sortপদক্ষেপটি -depthবিকল্পের পক্ষে বাদ দেওয়া যেতে পারে find
মাইকেল ক্রেলিন - হ্যাকার

1
যদি কোনও ফাইলনেমে \ (ব্যাকস্ল্যাশ) থাকে তবে কাজ করে না । -rপড়ার বিকল্প যুক্ত করে ঠিক করা যায় ।
jfg956

8
আপনার সমাধানটি অনুলিপি করতে এবং এটি ব্যবহার করতে এই পৃষ্ঠাটি আমি অবশ্যই 50 তম বার দেখা উচিত। আপনাকে অনেক ধন্যবাদ । আমি আপনার উত্তরটিকে পছন্দ করি, কারণ আমি ম্যাকের সাথে আছি এবং renameডেনিসের দ্বারা প্রস্তাবিত আদেশটি নেই।
অ্যালেক্স কনস্টান্টিন

@AlexConstantin, তাই না macportsআছে rename? আমি কখনই এটি খুঁজে বের করার মাথা ঘামাইনি কারণ আমি মনে করি না যে টাস্কটি ইউটিলিটিটিকে ন্যায়সঙ্গত করে। এবং যদি আপনার না থাকে তবে আপনার macportsসেগুলি ইনস্টল করার বিষয়টি বিবেচনা করা উচিত;)
মাইকেল ক্রেলিন - হ্যাকার

30

আপনি detoxডগ হার্পেল দ্বারা ব্যবহার করতে পারেন

detox -r <folder>

12

একটি সন্ধান / নতুন নাম সমাধান। নতুন নামটি ইউজার-লিনাক্সের অংশ।

আপনাকে প্রথমে গভীরতা অবতরণ করতে হবে, কারণ একটি সাদা স্থান ফাইল নাম একটি সাদা স্থানের ডিরেক্টরিতে অংশ হতে পারে:

find /tmp/ -depth -name "* *" -execdir rename " " "_" "{}" ";"

আমি আপনার চালানোর সময় আমি কোনও পরিবর্তন পাই না।
পরবর্তী বিজ্ঞপ্তি না হওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

ইউজার-লিনাক্স সেটআপ চেক করুন: $ পুনর্নবীকরণ
জর্জেন হ্যাটজেল

গ্রেপিং / ইউএসআর / বিন / পুনর্নবীকরণ (একটি পার্ল স্ক্রিপ্ট) "সংশোধন 1.5 1998/12/18 16:16:31 আরএমবি 1" প্রকাশ করে
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত

হুম ... আপনার ইউজ-লিনাক্স বাইনারি কোথায় গেল? এই ফাইল পাথটি ইউজ-লিনাক্সের মালিকানাধীন হওয়া উচিত। আপনি কি আমাদের একটি জিএনইউ-লিনাক্স সিস্টেম নন?
জর্জেন হ্যাটজেল

1
যা আমার দৌড়ে কেবল একটি স্থান পরিবর্তন করে , তাই "পর্বতের উপরে আগুন বলুন" "পর্বতের উপরে আগুন" হয়ে যায়।
ব্রোকার

6

bash 4.0

#!/bin/bash
shopt -s globstar
for file in **/*\ *
do 
    mv "$file" "${file// /_}"       
done

দেখে মনে হচ্ছে এটি কোনও a' to a subdirectory of itself,
এমভি

কিছু যায় আসে না। কেবল পুনর্নির্দেশের মাধ্যমে ত্রুটি বার্তাটি সরান /dev/null
ghostdog74

ঘোস্টডগ, mvকেবল চারটি ফাইলের নাম পরিবর্তন করতে পঞ্চাশ হাজার বার প্রসারিত করা যদি আপনি বার্তাগুলি সহ ব্যবহারকারীদের বন্যা না করেন তবে কিছুটা ওভারহেড হতে পারে।
মাইকেল ক্রেলিন - হ্যাকার

ক্রেলিন, এমনকি সন্ধান করা 555 টি ফাইলের মধ্যে দিয়ে অনুসন্ধানগুলি ফাঁকা স্থানগুলি খুঁজে পেতে এবং তারপরে পুনরায় নামকরণ করতে পারবেন। শেষ প্রান্তে, এটি এখনও সমস্ত মাধ্যমে চলছে। আপনি যদি চান তবে নাম পরিবর্তনের আগে স্পেসের জন্য প্রাথমিক চেক এটি করবে it
ghostdog74

আমি এমভি স্প্যানিংয়ের কথা বলছিলাম, যাচ্ছি না। না for file in *' '*বা এই জাতীয় কিছু আরও ভাল কাজ করতে পারে?
মাইকেল ক্রেলিন - হ্যাকার

6

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

    find . -name '* *' | while read fname 

do
        new_fname=`echo $fname | tr " " "_"`

        if [ -e $new_fname ]
        then
                echo "File $new_fname already exists. Not replacing $fname"
        else
                echo "Creating new file $new_fname to replace $fname"
                mv "$fname" $new_fname
        fi
done

3

নাইদিমের উত্তরগুলির পুনরাবৃত্তি সংস্করণ।

find . -name "* *" | awk '{ print length, $0 }' | sort -nr -s | cut -d" " -f2- | while read f; do base=$(basename "$f"); newbase="${base// /_}"; mv "$(dirname "$f")/$(basename "$f")" "$(dirname "$f")/$newbase"; done

2

এখানে একটি (বেশ ভার্জোজাল) অনুসন্ধান-সমাধান সমাধান যা "ফাইল ইতিমধ্যে বিদ্যমান" stderr সম্পর্কে সতর্কতা লিখেছে:

function trspace() {
   declare dir name bname dname newname replace_char
   [ $# -lt 1 -o $# -gt 2 ] && { echo "usage: trspace dir char"; return 1; }
   dir="${1}"
   replace_char="${2:-_}"
   find "${dir}" -xdev -depth -name $'*[ \t\r\n\v\f]*' -exec bash -c '
      for ((i=1; i<=$#; i++)); do
         name="${@:i:1}"
         dname="${name%/*}"
         bname="${name##*/}"
         newname="${dname}/${bname//[[:space:]]/${0}}"
         if [[ -e "${newname}" ]]; then
            echo "Warning: file already exists: ${newname}" 1>&2
         else
            mv "${name}" "${newname}"
         fi
      done
  ' "${replace_char}" '{}' +
}

trspace rootdir _

2

এই একটি আরও একটু বেশি করে। আমি এটি আমার ডাউনলোড করা টরেন্টসটির নাম পরিবর্তন করতে (কোনও বিশেষ অক্ষর (অ-এএসসিআইআই নয়), স্পেসস, একাধিক বিন্দু, ইত্যাদি) ব্যবহার করতে ব্যবহার করি।

#!/usr/bin/perl

&rena(`find . -type d`);
&rena(`find . -type f`);

sub rena
{
    ($elems)=@_;
    @t=split /\n/,$elems;

    for $e (@t)
    {
    $_=$e;
    # remove ./ of find
    s/^\.\///;
    # non ascii transliterate
    tr [\200-\377][_];
    tr [\000-\40][_];
    # special characters we do not want in paths
    s/[ \-\,\;\?\+\'\"\!\[\]\(\)\@\#]/_/g;
    # multiple dots except for extension
    while (/\..*\./)
    {
        s/\./_/;
    }
    # only one _ consecutive
    s/_+/_/g;
    next if ($_ eq $e ) or ("./$_" eq $e);
    print "$e -> $_\n";
    rename ($e,$_);
    }
}

1

আমি এই স্ক্রিপ্টের চারপাশে খুঁজে পেয়েছি, এটি আকর্ষণীয় হতে পারে :)

 IFS=$'\n';for f in `find .`; do file=$(echo $f | tr [:blank:] '_'); [ -e $f ] && [ ! -e $file ] && mv "$f" $file;done;unset IFS

তাদের নামে নতুন লাইনের ফাইলগুলিতে ব্যর্থ।
ঘোটি


1

যারা ম্যাকোস ব্যবহার করে এটির জন্য লড়াই করছেন তাদের জন্য প্রথমে সমস্ত সরঞ্জাম ইনস্টল করুন:

 brew install tree findutils rename

তারপরে পুনরায় নামকরণ করার সময়, জিএনইউ ফাইন্ড (জিফাইন্ড) হিসাবে সন্ধানের জন্য একটি উপাধি তৈরি করুন। তারপরে @ মিশেল ক্রেলিনের কোডটি চালান:

alias find=gfind 
find . -depth -name '* *' \
| while IFS= read -r f ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr ' ' _)" ; done   

0

এটি কেবলমাত্র বর্তমান ডিরেক্টরিতে ফাইল খুঁজে পায় এবং তাদের নতুন নাম দেয় । আমি এই এলিয়াস আছে।

find ./ -name "* *" -type f -d 1 | perl -ple '$file = $_; $file =~ s/\s+/_/g; rename($_, $file);


0

আমি কেবল নিজের উদ্দেশ্যে তৈরি করি। আপনি এটি রেফারেন্স হিসাবে ব্যবহার করতে পারেন।

#!/bin/bash
cd /vzwhome/c0cheh1/dev_source/UB_14_8
for file in *
do
    echo $file
    cd "/vzwhome/c0cheh1/dev_source/UB_14_8/$file/Configuration/$file"
    echo "==> `pwd`"
    for subfile in *\ *; do [ -d "$subfile" ] && ( mv "$subfile" "$(echo $subfile | sed -e 's/ /_/g')" ); done
    ls
    cd /vzwhome/c0cheh1/dev_source/UB_14_8
done


0

সমস্যার সমাধান আমার ব্যাশ স্ক্রিপ্ট:

#!/bin/bash
directory=$1
cd "$directory"
while [ "$(find ./ -regex '.* .*' | wc -l)" -gt 0 ];
do filename="$(find ./ -regex '.* .*' | head -n 1)"
mv "$filename" "$(echo "$filename" | sed 's|'" "'|_|g')"
done

স্ক্রিপ্টটি কার্যকর করার পরে আর্গুমেন্ট হিসাবে আপনি যে ডিরেক্টরিটির নামটি স্ক্রিপ্টটি প্রয়োগ করতে চান সেটি কেবল রেখে দিন।


0

ম্যাকোজে

ঠিক যেমন নির্বাচিত উত্তর।

brew install rename

# 
cd <your dir>
find . -name "* *" -type d | rename 's/ /_/g'    # do the directories first
find . -name "* *" -type f | rename 's/ /_/g'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.