Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

massig datein umbenennen

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

Benutzeravatar
Robert.B
Member
Member
Beiträge: 69
Registriert: 2. Feb 2005, 21:37

massig datein umbenennen

Beitrag von Robert.B »

gibt es ein programm/scrip mit dem ich in einen rutsch mehrere datein (mehrer 100) in einen zum umbenennen kann?

es sollen die leerzeichen durch _ ersetzt werden (ist "linux-freundlicher")
rodhel
Newbie
Newbie
Beiträge: 5
Registriert: 9. Feb 2005, 10:06

Beitrag von rodhel »

kenne mich nicht so besonders aus, aber evtl. kann man find (mit -exec) mit sed und mv kombinieren.

mit sed können Zeichenketten bearbietet werden (reguläre Ausdrücke), es gibt noch etwas besseres (für diesen Anwendungsfall), was nur Zeichen austauscht, mir fällt jetzt aber nicht ein wie es heisst...
Benutzeravatar
scg
Hacker
Hacker
Beiträge: 399
Registriert: 4. Jul 2004, 09:56
Wohnort: Nürnberg (SuSE-City)
Kontaktdaten:

Beitrag von scg »

Wär doch was für unsere Script-Masters....

Also Leute, das kürzeste kommt in die Skriptsammlung !
CU scg
Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3174
Registriert: 25. Aug 2004, 02:13

Beitrag von robi »

Code: Alles auswählen

#! /bin/bash
find . -name "?* *" | while read DATEI
do
 DATEI_NEU=`echo $DATEI | tr " " "_"`
 mv "${DATEI}"  "${DATEI_NEU}" 
done
versuche mal das Script

unfaire den Wettbewerbsaushang wurde reingesetzt als ich beim entwickeln war

robi
Zuletzt geändert von robi am 9. Feb 2005, 21:33, insgesamt 1-mal geändert.
Calvin
Hacker
Hacker
Beiträge: 285
Registriert: 8. Mai 2004, 00:19

Beitrag von Calvin »

Mit dem Programm krename funktioniert das auch problemlos.
Benutzeravatar
TeXpert
Guru
Guru
Beiträge: 2166
Registriert: 17. Jan 2005, 11:22

Beitrag von TeXpert »

robi hat geschrieben:

Code: Alles auswählen

#! /bin/bash
find . -name "?* *" | while read DATEI
do
 DATEI_NEU=`echo $DATEI | tr " " "_"`
 mv "${DATEI}"  "${DATEI_NEU}" 
done
versuche mal das Script
robi
autsch, es gibt ja "useless use of cat" aber dass es mittlerweile auch useless use of find and read :)

Problem durch das move können Dateien überschrieben werden, wenn also 'mv foo\ bar foo_bar' ausgeführt wird aber bereits existiert.... Pech. Lösung wäre mv -i dann fallen diese Fälle zumindest auf.

Alternativvorschlag, erst mal ohne Optimierung bzgl. des Fehlers und nur mit mv als externem Prog, der Rest geht alles bash-intern

Code: Alles auswählen

#!/bin/bash
for f in *\ *
do
  mv "$f" "${f/ /_}"
done
um ein Überschreiben zu verhinden können wir noch eine Abfrage einbauen und zusätzlich werden alle ignorierten Dateien glistet

Code: Alles auswählen

#!/bin/bash
for f in *\ *
do
  if [ -e "${f/ /_}" ]
  then
     echo "${f/ /_}" >> problem_dateien.txt
  else
    mv "$f" "${f/ /_}"
  fi
done
wobei krename doch sicherlich sinnvoller ist :)
Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3174
Registriert: 25. Aug 2004, 02:13

Beitrag von robi »

@TeXpert

ich versteh nur die Hälft von deinem Script aber es läuft bei mir auf error und zwar genau dann wenn es nichts zum umbennen mehr gibt.
So sinnlos ist die "find| while read" Kombination nun wohl doch nicht.
~/test> ./test
mv: Aufruf von stat für ,,* *" nicht möglich: Datei oder Verzeichnis nicht gefunden
~/test>
Keine Ahnung was das bedeuten soll.
Ein Metazeichen wird niemals vom jeweiligen Kommando interpretiert, sondern immer von der Shell. Aus diesem Grund funktioniert ein Kommando wie
user@sonne> cp *.x *.y

unter einer Unix -Shell nicht.
kann es vielleicht daran liegen????

geht das in deiner Schreibweise auch dass er nicht nur immer 1 Leerzeichen sondern gleich alle ändert?

robi
Benutzeravatar
Robert.B
Member
Member
Beiträge: 69
Registriert: 2. Feb 2005, 21:37

Beitrag von Robert.B »

also das iss schon mal ganz gut :D
danke

aber

geht es auch das datein in ordnern umbenannt werden?

und

gehts nicht auch in einen staz...
ich muss das proggy immer x-mal starten...
Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3174
Registriert: 25. Aug 2004, 02:13

Beitrag von robi »

Robert.B hat geschrieben:also das iss schon mal ganz gut :D
danke aber geht es auch das datein in ordnern umbenannt werden?
und gehts nicht auch in einen staz...
ich muss das proggy immer x-mal starten...
Ihr wollt es ja wieder mal ganz genau haben, TeXpert wirds zwar wieder in der Luft zerreisen, aber bitte.

Code: Alles auswählen

#! /bin/bash
if [ $# -ne 1 ]; then echo "Aufruf: programm verzeichnis";fi
cd "$1"
find . -mindepth 1 -maxdepth 1  | while read DATEI
do
  if [ -d "${DATEI}" ]; then
     $0 "${DATEI}"
  fi
  if [ $(echo $DATEI | grep " " | wc -l ) = 1 ]; then
     DATEI_NEU=`echo $DATEI | tr " " "_"`
     mv "${DATEI}" "${DATEI_NEU}"
  fi
done
Muss aber gleich ein paar Einschränkungen machen.
Das script muss im PATH sein oder mit vollem PATH/script aufgerufen werden und erwartet als Parameter das Verzeichniss in dem die Dateien stehen.
also

Code: Alles auswählen

script ./verzeichnis
es wird allerdings Dateienamen die am Ende ein oder mehrere Leerzeichen haben auch nicht umbenennen können, nur wer solche Dateien anlegt, der gehört sowieso erschossen. :evil:

robi
Benutzeravatar
oc2pus
Ultimate Guru
Ultimate Guru
Beiträge: 6506
Registriert: 21. Jun 2004, 13:01

Beitrag von oc2pus »

warum plagt ihr euch so ?

schaut bei freshmeat.net vorbei ... suchabfrage "rename"
==> 90 scripte und tools ... mit GUI ohne GUI, in bash perl was weiß ich nicht alles ...

@scg
was gibt es zu gewinnen *fg* ... sonst macht es ja keinen Spaß :)
tell people what you want to do, and they'll probably help you to do it.
PackMan
LinWiki : Das Wiki für Linux User
Benutzeravatar
TeXpert
Guru
Guru
Beiträge: 2166
Registriert: 17. Jan 2005, 11:22

Beitrag von TeXpert »

@robi, ups, siehste :) da war ein kleiner Schnelltipper drin, mach aus den

Code: Alles auswählen

${f/ /_}
ein

Code: Alles auswählen

${f// /_}
dann werden alle ersetzt.

Die Fehlermeldung ja, ja das ist ja klar aber ein mv oder ein cp oder sonst was gibt Dir bei nicht existierenden Dateien auch eine Fehlermeldung ... das liegt daran, dass das Globbing nichts matched.

das lässt sich aber einfach umgehen, indem Du vorne noch eine Weiche vorsetzt, alternativ kann man auch einfach die mv -Fehlermeldung nach dev-Null umleiten

Code: Alles auswählen

 #!/bin/bash
for f in *\ *
do
  if [ ! -e "$f" ] ; then exit 1 ; fi
  if [ -e "${f// /_}" ]
  then
     echo "$(pwd)/${f// /_}" >> probleme
  else
    mv "$f" "${f// /_}"
  fi
done
Verzeichnisse kann man sicherlich dann mit find durchnudeln :) aber ich hab jetzt mal die Herausforderung angenommen: außer mv und [ sind nur noch bash-Konstrukte drin :) das ganze musste mit Funktionen gemacht werden, da ich ja eine Rekursive Suche durchführen muss, ich mache iene Tiefensuche, damit ich erst in die Verzeichnisse reinsteige, bevor ich die umbenenne!

Code: Alles auswählen

#!/bin/bash

# pfad für die Logdatei
CWD=`pwd`
LOG="$CWD/probleme.txt"


# benenne alle Dateien um
space2underline() {
  for f in *\ *
  do
    if [ ! -e "$f" ] ; then return ; fi
    if [ -e "${f// /_}" ]
    then
       echo "$(pwd): $f -- > ${f// /_} Datei existiert" >> "$LOG"
    else
      mv "$f" "${f// /_}"
    fi
  done
}

# rekursive tiefensuche
DFS() {
  for i in *
  do
    [ -d "$i" ] || continue
    cd "$i"
    DFS
    cd ..
  done
  # aktuelles Verzeichnis bearbeiten
  space2underline
}


# tiefensuche starten
DFS

Vorteil: der Code muss nicht im Pfad liegen, macht keien weiteren Annahmen.


@oc2pus: das ist eine kleine geistige Spielerei und Bash-training :)
Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3174
Registriert: 25. Aug 2004, 02:13

Beitrag von robi »

@TeXpert
Auf den ersten Blick sieht dein Script ja relativ normal aus, werde es heute abend mal austesten. Was mir auf dem erstem Blick aufgefallen ist, es ignoriert versteckte Dateien.
Kannst du mal ${f// /_} ein bisschen genauer erklären?, habe diese Schreibweise so noch nie vorher gesehen.

Meine Rekursion ist dafür aber bedeutend gefährlicher, eine falsche Option im find und du hast die schönste forc-Bombe, durfte es selbst erleben. :lol:

Ich habe da noch ein paar Ideen wie man das auch noch anstellen könnte, aber muss erst testen ob sowas mit der Shell überhaut geht, jedenfalls wirds wenns funktioniert "Griechisch-Römisch-Freistiel".

@all Hat einer von euch nicht auch jemand Dateienamen mit Leerzeichen und Zeilenumbruch ??? Das wird dann eine richtige Herausforderung.

Wo ist denn hier die C-Shell und Perl Fraktion, kann man damit denn keine Dateien umbenennen?

robi
Benutzeravatar
TeXpert
Guru
Guru
Beiträge: 2166
Registriert: 17. Jan 2005, 11:22

Beitrag von TeXpert »

robi hat geschrieben:@TeXpert
Auf den ersten Blick sieht dein Script ja relativ normal aus, werde es heute abend mal austesten. Was mir auf dem erstem Blick aufgefallen ist, es ignoriert versteckte Dateien.
stimmt :) hier muss ich noch mal nachdenken...

(edit: Kaffee geholt, 5 minuten nachgedacht, hier ist die Lösung:

hinter der shebang-Zeile noch eine Shelloption setzten:

Code: Alles auswählen

shopt -s dotglob
edit ende)


dann werden auch dot-files ins globbing aufgenommen.
Kannst du mal ${f// /_} ein bisschen genauer erklären?, habe diese Schreibweise so noch nie vorher gesehen.
die Formen

Code: Alles auswählen

${VARIABLE IRGENDWAS}
gehört in die Gruppe der String-Manipulatoren der Bash,
Beispiele:

Code: Alles auswählen

#!/bin/bash

STRING="12345678901234567890"

#der string
echo "$STRING"
echo "${STRING}"

# substrings
echo "${STRING:4}"
echo "${STRING:4:2}"

echo "${STRING:-4}"
echo "${STRING:(-4)}"
echo "${STRING:(-4):2}"

#substring removal
echo ${STRING#1*6}
echo ${STRING##1*6}
echo ${STRING%7*0}
echo ${STRING%%7*0}

#replacement
echo ${STRING/3/_}
echo ${STRING//3/_}

echo ${STRING/#1/_}
echo ${STRING/%0/_}
[/code]
Zuletzt geändert von TeXpert am 10. Feb 2005, 12:41, insgesamt 2-mal geändert.
Benutzeravatar
oc2pus
Ultimate Guru
Ultimate Guru
Beiträge: 6506
Registriert: 21. Jun 2004, 13:01

Beitrag von oc2pus »

ok :)

man nehme TexPerts "Tiefensuche" und ersetze seine Funktion
space2underline() durch:

Code: Alles auswählen

space2underline() { 
    for datei in *; do 
        mv "$datei" "`echo $datei | sed -e 's/\ /_/g'`.mp3" 2> /dev/null; 
    done
}
wenn die Dateien schon die Endung ".mp3" haben, dann durch:

Code: Alles auswählen

mv "$datei" "`echo $datei | sed -e 's/\ /_/g'`" 2> /dev/null; 
tell people what you want to do, and they'll probably help you to do it.
PackMan
LinWiki : Das Wiki für Linux User
Benutzeravatar
TeXpert
Guru
Guru
Beiträge: 2166
Registriert: 17. Jan 2005, 11:22

Beitrag von TeXpert »

dann hast Du das Problem, wenn die Datei schon existiert, die wird dann überschrieben.


@robi: beachte mein Edit mit den Dotfiles
Benutzeravatar
oc2pus
Ultimate Guru
Ultimate Guru
Beiträge: 6506
Registriert: 21. Jun 2004, 13:01

Beitrag von oc2pus »

TeXpert hat geschrieben:dann hast Du das Problem, wenn die Datei schon existiert, die wird dann überschrieben.
nö, das gibt einen Fehler ;) aber dafür ist /dev/null da ...
mv: ,,rpm-tmp.16616.mp3" und ,,rpm-tmp.16616.mp3" sind die gleiche Datei
tell people what you want to do, and they'll probably help you to do it.
PackMan
LinWiki : Das Wiki für Linux User
Benutzeravatar
TeXpert
Guru
Guru
Beiträge: 2166
Registriert: 17. Jan 2005, 11:22

Beitrag von TeXpert »

Das ist aber nicht default! das gilt nur wenn Du Dir den mv Befehl auf mv -i mit alias gemapped hast, sonst wird das gnadenlos überschrieben.
> touch a
> touch b
> mv -i b a
mv: ,,a" überschreiben? n
> mv b a
>
Benutzeravatar
oc2pus
Ultimate Guru
Ultimate Guru
Beiträge: 6506
Registriert: 21. Jun 2004, 13:01

Beitrag von oc2pus »

TeXpert hat geschrieben:Das ist aber nicht default! das gilt nur wenn Du Dir den mv Befehl auf mv -i mit alias gemapped hast, sonst wird das gnadenlos überschrieben.
kann das an meiner bash liegen ?

Code: Alles auswählen

bash -version
GNU bash, version 3.00.0(1)-release (i586-suse-linux)
Copyright (C) 2004 Free Software Foundation, Inc.
robi hat geschrieben:Wo ist denn hier die C-Shell und Perl Fraktion, kann man damit denn keine Dateien umbenennen?
ok first dirty hack ....

Code: Alles auswählen

#!/usr/bin/perl
# Usage: rename perlexpr [files]
use File::Glob qw(:glob);

($regexp = shift @ARGV) || die "Usage:  rename perlexpr [filenames]\n";

if (!@ARGV) {
   @ARGV = <STDIN>;
   chomp(@ARGV);
}

foreach $_ (bsd_glob(@ARGV, GLOB_NOCASE)) {
   $old_name = $_;
   eval $regexp;
   die $@ if $@;
   rename($old_name, $_) unless $old_name eq $_;
}
exit(0);
damit würden dann die spaces durch "_" ersetzt
./rename.pl 's/\ /_/g' *

dann einen bash-wrapper drumherum, der das perl-Script aufruft:

Code: Alles auswählen

find "irgendeinverz" -print | tac | rename.pl '($file) = (m|.+/(.+)|); $file = $_ if (!defined($file)); ($newfile = $file) =~ s/ /_/g; s/$file/$newfile/;'
tell people what you want to do, and they'll probably help you to do it.
PackMan
LinWiki : Das Wiki für Linux User
Benutzeravatar
TeXpert
Guru
Guru
Beiträge: 2166
Registriert: 17. Jan 2005, 11:22

Beitrag von TeXpert »

oc2pus hat geschrieben:
TeXpert hat geschrieben:Das ist aber nicht default! das gilt nur wenn Du Dir den mv Befehl auf mv -i mit alias gemapped hast, sonst wird das gnadenlos überschrieben.
kann das an meiner bash liegen ?

Code: Alles auswählen

bash -version
GNU bash, version 3.00.0(1)-release (i586-suse-linux)
Copyright (C) 2004 Free Software Foundation, Inc.
veeery strange :o

hier läuft:

Code: Alles auswählen

 bash --version
GNU bash, version 3.00.0(1)-release (i586-suse-linux)
Copyright (C) 2004 Free Software Foundation, Inc.
ich nutze:

Code: Alles auswählen

> mv --version
mv (coreutils) 5.2.1
und ich hab keinen alias gesetzt:

Code: Alles auswählen

> alias | grep -i mv
alias move='echo '\''Error: Try the command: mv -iv'\'''
Benutzeravatar
oc2pus
Ultimate Guru
Ultimate Guru
Beiträge: 6506
Registriert: 21. Jun 2004, 13:01

Beitrag von oc2pus »

@TeXpert
habsch auch, gleiche mv Version wie du und keinen alias ... :shock:
tell people what you want to do, and they'll probably help you to do it.
PackMan
LinWiki : Das Wiki für Linux User
Antworten