Ik heb een map met ongeveer 1.700 bestanden. Ze hebben allemaal de naam 1.txt
of 1497.txt
, enz. Ik wil alle bestanden hernoemen zodat alle bestandsnamen vier cijfers lang zijn.
D.w.z. 23.txt
wordt 0023.txt
.
Wat is een shellscript dat dit doet? Of een gerelateerde vraag: Hoe gebruik ik grep om alleen regels te matchen die \d.txt
bevatten (dwz één cijfer, dan een punt, dan de letters txt
)?
Dit is wat ik tot nu toe heb:
for a in [command i need help with]
do
mv $a 000$a
done
Voer dat in principe drie keer uit, met opdrachten om een cijfer, twee cijfers en driecijferige bestandsnamen te vinden (waarbij het aantal beginnullen is gewijzigd).
Antwoord 1, autoriteit 100%
Probeer:
for a in [0-9]*.txt; do
mv $a `printf %04d.%s ${a%.*} ${a##*.}`
done
Wijzig het bestandsnaampatroon ([0-9]*.txt
) indien nodig.
Een algemene hernoemde naam die geen aannames doet over de initiële set bestandsnamen:
X=1;
for i in *.txt; do
mv $i $(printf %04d.%s ${X%.*} ${i##*.})
let X="$X+1"
done
Over hetzelfde onderwerp:
Antwoord 2, autoriteit 31%
Met behulp van het rename
(prename
in sommige gevallen) script dat soms met Perl is geïnstalleerd, kunt u Perl-expressies gebruiken om de hernoeming uit te voeren. Het script slaat het hernoemen over als er een naambotsing is.
De onderstaande opdracht hernoemt alleen bestanden met vier of minder cijfers gevolgd door de extensie “.txt”. Het hernoemt geen bestanden die niet strikt aan dat patroon voldoen. Namen die uit meer dan vier cijfers bestaan, worden niet afgekapt.
rename 'unless (/0+[0-9]{4}.txt/) {s/^([0-9]{1,3}\.txt)$/000$1/g;s/0*([0-9]{4}\..*)/$1/}' *
Een paar voorbeelden:
Original Becomes
1.txt 0001.txt
02.txt 0002.txt
123.txt 0123.txt
00000.txt 00000.txt
1.23.txt 1.23.txt
Andere antwoorden die tot nu toe zijn gegeven, zullen proberen bestanden te hernoemen die niet aan het patroon voldoen, fouten te produceren voor bestandsnamen die niet-cijferige tekens bevatten, hernoemingen uit te voeren die naambotsingen veroorzaken, proberen en falen om bestanden te hernoemen met spaties in hun namen en mogelijk andere problemen.
Antwoord 3, autoriteit 26%
for a in *.txt; do
b=$(printf %04d.txt ${a%.txt})
if [ $a != $b ]; then
mv $a $b
fi
done
Antwoord 4, autoriteit 17%
One-liner:
ls | awk '/^([0-9]+)\.txt$/ { printf("%s %04d.txt\n", $0, $1) }' | xargs -n2 mv
Hoe gebruik ik grep om alleen regels te matchen die \d.txt bevatten (IE 1 cijfer, dan een punt, dan de letters txt)?
grep -E '^[0-9]\.txt$'
Antwoord 5, autoriteit 9%
Laten we aannemen dat je bestanden met datatype .dat in je map hebt staan. Kopieer deze code gewoon naar een bestand met de naam run.sh, maak het uitvoerbaar door chmode +x run.sh
uit te voeren en voer het vervolgens uit met ./run.sh
:
#!/bin/bash
num=0
for i in *.dat
do
a=`printf "%05d" $num`
mv "$i" "filename_$a.dat"
let "num = $(($num + 1))"
done
Hiermee worden alle bestanden in uw map geconverteerd naar filename_00000.dat
, filename_00001.dat
, enz.
Antwoord 6, autoriteit 2%
Deze versie ondersteunt ook het verwerken van strings voor (na) het nummer. Maar in principe kun je elke regex-matching+printf doen, zolang je awk dit ondersteunt. En het ondersteunt ook witruimtetekens (behalve nieuwe regels) in bestandsnamen.
for f in *.txt ;do
mv "$f" "$(
awk -v f="$f" '{
if ( match(f, /^([a-zA-Z_-]*)([0-9]+)(\..+)/, a)) {
printf("%s%04d%s", a[1], a[2], a[3])
} else {
print(f)
}
}' <<<''
)"
done
Antwoord 7
Als u alleen tekstbestanden met één cijfer wilt matchen, kunt u het volgende doen…
$ ls | grep '[0-9]\.txt'
Antwoord 8
Hint in één zin:
while [ -f ./result/result`printf "%03d" $a`.txt ]; do a=$((a+1));done
RESULT=result/result`printf "%03d" $a`.txt
Antwoord 9
Om een oplossing te bieden die zorgvuldig is geschreven om correct te zijn, zelfs in de aanwezigheid van bestandsnamen met spaties:
#!/usr/bin/env bash
pattern='%04d' # pad with four digits: change this to taste
# enable extglob syntax: +([[:digit:]]) means "one or more digits"
# enable the nullglob flag: If no matches exist, a glob returns nothing (not itself).
shopt -s extglob nullglob
for f in [[:digit:]]*; do # iterate over filenames that start with digits
suffix=${f##+([[:digit:]])} # find the suffix (everything after the last digit)
number=${f%"$suffix"} # find the number (everything before the suffix)
printf -v new "$pattern" "$number" "$suffix" # pad the number, then append the suffix
if [[ $f != "$new" ]]; then # if the result differs from the old name
mv -- "$f" "$new" # ...then rename the file.
fi
done
Antwoord 10
Er is standaard een rename.ul
commando geïnstalleerd vanuit het util-linux
pakket (tenminste in Ubuntu).
Het gebruik is (do a man rename.ul):
hernoem [opties] expressievervangingsbestand…
De opdracht vervangt de eerste keer dat expression
voorkomt door de gegeven replacement
voor de geleverde bestanden.
Terwijl je het commando vormt, kun je het volgende gebruiken:
rename.ul -nv replace-me with-this in-all?-these-files*
om geen wijzigingen aan te brengen, maar om te lezen welke wijzigingen dat commando zou aanbrengen. Als je zeker weet, voer je de opdracht opnieuw uit zonder de opties -v (uitgebreid) en -n (no-act)
in jouw geval zijn de commando’s:
rename.ul "" 000 ?.txt
rename.ul "" 00 ??.txt
rename.ul "" 0 ???.txt