Ubuntu Suomen keskustelualueet
Ubuntun käyttö => Ohjelmointi, palvelimet ja muu edistyneempi käyttö => Aiheen aloitti: jekku - 20.05.13 - klo:13.11
-
Olisi tehtävä muutama operaatio useassa hakemistossa mutta ohitettava sellaiset jotka linkitetty myös eri nimelle. Milläs kaivelen em. tiedon?
Toisin sanoen, on muutama hakemisto
/mnt/duuni1
/mnt/duuni2
/mnt/duuni3
/mnt/duuni4
ja symbolinen linkki
/mnt/vuorossa -> /mnt/duuni2
Joten silmukassa olisi loikattava tuon /mnt/duuni2 yli.
-
Äkkiseltään sanoisin, ettet mitenkään. Linkki tietää olevansa linkki, mutta linkin kohde ei tiedä siihen linkatun.
Toisinpäin kuitenkin onnistuu, joten jos tiedät juuren josta etsiä, voisiko hommaa lähestyä näin: jos juuri on esim. /mnt kuten esimerkissäsi,
- käyt kansion ensin läpi ja keräät kaikki linkit
- sitten käyt linkit läpi ja keräät niiden kohteet
- ja lopuksi siinä vaiheessa, kun käyt kansiota työvaiheessa läpi, ohitat löydetyt kohteet
-
Äkkiseltään sanoisin, ettet mitenkään. Linkki tietää olevansa linkki, mutta linkin kohde ei tiedä siihen linkatun.
Toisinpäin kuitenkin onnistuu, joten jos tiedät juuren josta etsiä, voisiko hommaa lähestyä näin: jos juuri on esim. /mnt kuten esimerkissäsi,
- käyt kansion ensin läpi ja keräät kaikki linkit
- sitten käyt linkit läpi ja keräät niiden kohteet
- ja lopuksi siinä vaiheessa, kun käyt kansiota työvaiheessa läpi, ohitat löydetyt kohteet
Nojoo, nuo hakemistot joihin on linkki luulen löytäneeni komennolla
find . -maxdepth 1 -type l -exec readlink {} \;
Mutta juurikin tuo ohittaminen on nyt hukassa...
-
find . -maxdepth 1 -type l -exec readlink {} \;
Eli mennään juuri niin päin kuin sanoinkin: readlink kertoo, mihin annettu linkki viittaa. Nämä voisit nyt kerätä johonkin muuttujaan listaksi ja silmukassa testata, löytyykö kulloinenkin nimi tästä listasta.
Mutta tuota noin... Esimerkkisi oli sen verran simppeli, että olen ehkä ihan metsässä, mutta eikö mielekkäämpää olisi silmukassa testata, onko annettu nimi linkki ja ohittaa se, jos on? Ts. esimerkissäsi ei ohitettaisi kansiota /mnt/duuni2 (koska se on linkin kohde) mutta ohitettaisiinkin sen sijaan /mnt/vuorossa, koska se on linkki kohteeseen /mnt/duuni2.
Muoks: Siis osapuilleen näin:
for f in /mnt/*; do
[ ! -h $f ] && echo Käsitellään $f...
done
Tuo ”! -h $f” tarkoittaa siis ”jollei $f ole symbolinen linkki”. Hakasulkeet kannattaa korvata kaksoishakasulkeilla, jollei sh-yhteensopivuus ole tärkeää.
-
Mutta juurikin tuo ohittaminen on nyt hukassa...
Huutomerkki tai "-not" kääntää merkityksen "find" ssa:
find . -maxdepth 1 ! -type l
tai
find . -maxdepth 1 -not -type l
Tästä jälkimmäisestä find: in manuska sanoo että "ei ole POSIX yhteensopiva".
-
----
Eli mennään juuri niin päin kuin sanoinkin: readlink kertoo, mihin annettu linkki viittaa. Nämä voisit nyt kerätä johonkin muuttujaan listaksi ja silmukassa testata, löytyykö kulloinenkin nimi tästä listasta.
Mutta tuota noin... Esimerkkisi oli sen verran simppeli, että olen ehkä ihan metsässä, mutta eikö mielekkäämpää olisi silmukassa testata, onko annettu nimi linkki ja ohittaa se, jos on? Ts. esimerkissäsi ei ohitettaisi kansiota /mnt/duuni2 (koska se on linkin kohde) mutta ohitettaisiinkin sen sijaan /mnt/vuorossa, koska se on linkki kohteeseen /mnt/duuni2.
----
Arvelin hakevani silmukkaan vain hakemistot, joten /mnt/vuorossa ei edes tule mukaan,
mutta ohittaa pitäisi /mnt/duuni2
Ja siinä kohtaa on musta aukko. Kun ei tule mieleen tarkkaa hakuehtoa listalta/taulukosta joka tarttuisi merkkijonoon /mnt/duuni2 vaan ei reagoisi merkkijonoon /mnt/duuni22 tai /mnt/duuni2138
Edit:
Ja sitten QnD -ratkaisuna
for pd in $(ls)
do
value=$pd
if [ -d $value ] # kunhan tarkistan..
then
if [[ "${saved_dirs[@]}" =~ "${value} " || "${saved_dirs[${#saved_dirs[@]}-1]}" == "${value}" ]]; then
echo "hakemisto $value on suojattu, loikataan yli"
else
echo "${value}: Ei suojattu, joten:"
# ja se käsittely tähän...
fi
fi
done
Nuo ohitettavat on kerätty erikseen tuohon taulukkoon, saved_dirs
-
Migreenin keskeltä, vaikka ajatushan ei juokse ja vastaanko edes oikeaan kysymykseen:
Entäpä:
sudo apt-get install symlinks
symlinks -r $(pwd)
-
Kun ei tule mieleen tarkkaa hakuehtoa listalta/taulukosta joka tarttuisi merkkijonoon /mnt/duuni2 vaan ei reagoisi merkkijonoon /mnt/duuni22 tai /mnt/duuni2138
Entäpä jos sitä saved_dirsiä kävisi läpi for-silmukalla? for’han käy läpi mitä vain välilyönnein erotettua jonoa. Tyyliin (testaamatta):
dont_do_anything=0
for f in *; do
if [ -d $f ]; then
for g in ${saved_dirs}; do
if [ $f = $g ]; then
dont_do_anything=1
break # onkokaan sh:ssä breakiä?
fi
done
if [ ${dont_do_anything} -eq 0 ]; then
# nyt prosessoidaan...
fi
fi
done
-
En tiedä onko tästä apua mutta taulukkoa ei pysty (?) vertaamaan suoraan vaan vertailu pitää tehdä käymällä silmukalla taulukkoa läpi solu solulta yksi alkio kerrallaan sitä arvoa/merkkijonoa vastaan joka on kyseessä eli tuohon tyyliin kuin "SuperOscar" ehdottaa.
-
Vähän nätemmän tuosta saisi Pythonilla, mutta kieltämättä Pythonista voi olla komentotulkkiskriptiä vaikeampaa kutsua ulkoisia ohjelmia.
#!/usr/bin/env python
from os import listdir
from os.path import isdir, islink, join
# Edellä annettu muuttujien arvoiksi esim.
# root = '/mnt'
# saved_dirs = ['/mnt/duuni2']
for name in listdir(root):
path = join(root, name)
if isdir(path) and not islink(path) and path not in saved_dirs:
pass # Tähän prosessointi
-
Tuosta saisi rakenteellisesti nätimmän myös bash: llä kun kirjoittaisi erillisen funktion joka tekee vain testauksen.
-
Tuosta saisi rakenteellisesti nätimmän myös bash: llä kun kirjoittaisi erillisen funktion joka tekee vain testauksen.
Asennekysymys.
Jos testiä kutsutaan vain yhdessä kohdassa niin mieluummin kirjoitan sen suoraan siihen kohtaan.
Onpahan helpompaa esim. vuoden kuluttua lukea jotta mitä tulikaan tehtyä ;)
Tosin on monta työkaveria jotka ensi töikseen miettivät millaiset funktiot tarvitaan ja sitten missä järjestyksessä niitä kutsutaan, jos lainkaan ;)