Système de fichiers

On s'intéresse dans cet exercice au système de fichiers sur un ordinateur. On considère dans ce cadre les deux éléments suivants :

  • des fichiers, représentés en machine par des tuples au format (nom_du fichier, None). nom_du_fichier est une chaîne de caractères ;

  • des dossiers, représentés en machine par des tuples au format (nom_du_dossier, liste_des_enfants). nom_du_dossier est une chaîne de caractères, liste_des_enfants est une liste contenant de nouveaux éléments (fichiers ou dossiers).

L'exemple ci-dessous est constitué d'un dossier nommé racine contenant un fichier (un.py) et un sous-dossier (nommé sous_dossier) contenant lui-même deux fichiers (deux.pdf et trois.jpg) :

Système de fichier
racine
├───un.py
└───sous_dossier
    ├───deux.pdf
    └───trois_jpg

Ce dossier est représenté en machine par le tuple :

Représentation en Python
("racine", [("un.py", None), ("sous_dossier", [("deux.pdf", None), ("trois.jpg", None)])])

On fournit deux fonctions, est_fichier et est_dossier, indiquant, pour un élément quelconque, s'il s'agit d'un fichier ou d'un dossier :

🐍 Console Python
>>> elt = ("un.py", None)
>>> est_fichier(elt)
True
>>> est_dossier(elt)
False
>>> elt = ("dossier_vide", [])
>>> est_fichier(elt)
False
>>> est_dossier(elt)
True
Code des deux fonctions
🐍 Script Python
def est_fichier(elt):
    return elt[1] is None

def est_dossier(elt):
    return type(elt[1]) is list

On cherche dans cet exercice, étant donné un dossier, à calculer le nombre de dossiers et de fichiers qu'il contient ainsi que sa profondeur et le contenu d'un de ses sous-dossiers descendant.

1. Nombre de dossiers

Écrire la fonction nb_dossiers qui prend en paramètre un tuple représentant un dossier et renvoie le nombre de dossiers que celui-ci contient au total : lui-même et ses sous-dossiers ainsi que les sous-dossiers de ceux-ci...

Exemples
>>> dossier_nsi = ("nsi", [("tp1.py", None), ("tp1.pdf", None)])
>>> nb_dossiers(dossier_nsi)
1
>>> dossier_doc = ("documents", [("photo.jpg", None), dossier_nsi])
>>> nb_dossiers(dossier_doc)
2

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135[tf4)+2r3sao iugm1]P6pnlhe=cy:v(wS/b_dk050N0B0d0m0p0z0l0o0D0z0m0l0l0C010d0p0x010406050l0q0s0s0m0j0E040J0n0z0q0)0n0y050K0:0=0@0_0.0x041219051c0K1c1e190.0N0p0G0X0Z0#0%0A0p0r0A0z1s0A0d0,050S0L0z0B1n0!0$011r1t1v1t0d1B1D1z0d0L0n0N0_1A0j1a0d0A0X0|0l0x0m0y0%0i011F1p010e0U0B0y0m0s0B1z1%1)1.1H1;1D1@1_0,0a0o0v0j0n0x0n0l0p0 0y0o0Q1#0j0j0B0D2e121|0y1a0K1Z2r0d1X1W1Y0N1~0%1v0y1?2b1z1k1m0Y1G2B0p2D0y1T1l1z0x2k1a2p2r2V0/1(2f2J1/2O0j0?0z0,0t2o2Z0-2Y1}2#1H2%2)0,0i2-1)2/2p2A012@0m2*040k2{2q0.2~2=0%31330f362}2Z2 3c0,0b3f383h3a300n2(320,0w3f1b2T122H2u0N2y2 0D1T1`1a3A1d3y2X132.053F0Q2U3o1o1H0O0,0Q0e3w393U0%0I0,0o3!3T2K300e0,0y0L0M0N2b2c0B0j0l3+2;3$010+040H3}2!3 0y3X3^0p3`442 410g0F3m0o4i3*3#3-47040d3f4k3,1/0n0,0C4q2:453-0s0p2+4h4j4y2 3W040e3r4x4l2$0,0B0z4p3N2|4r3~3-0n3(042M4M4s2?480#4a0j4c3p410c4-3 4B4D4T2q4G4.0,0u4g4^0-4j514V4z1/4I0p3Z4 533i4P0l0d3?494b4 4`3 41435i4N4(044Q4S2X5o0%4e4~2V06525A5a3p4n5s2.5C3 4u040h4w595j4m3:3=3@4*3`3|5n4%5v0,5m5t5X304P4R4;3-4e4E4i5O550,2k0d0q0j115N5u5%4o3m123Q0B2r2S613z1l3B2u2w2s1S1U2u0m1C640K3A0.6h0R0T0V04.
2. Nombre de fichiers

Écrire la fonction nb_fichiers qui prend en paramètre un tuple représentant un dossier et renvoie le nombre de fichiers que celui-ci contient au total : ses fichiers mais aussi ceux présents dans ses sous-dossiers et les sous-dossiers de ceux-ci...

Exemples
>>> dossier_nsi = ("nsi", [("tp1.py", None), ("tp1.pdf", None)])
>>> nb_fichiers(dossier_nsi)
2
>>> dossier_doc = ("documents", [("photo.jpg", None), dossier_nsi])
>>> nb_fichiers(dossier_doc)
3

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135[tf4)+2r3sao iug08m1]P6pnl7he=cy:v(wS/b_dk050Q0E0d0m0p0B0l0o0G0B0m0l0l0F010d0p0z010406050l0q0u0u0m0j0H040M0n0B0q0,0n0A050N0?0^0`0|0;0z04151c051f0N1f1h1c0;0Q0p0J0!0$0(0*0D0p0r0D0B1v0D0d0/050V0O0B0E1q0%0)011u1w1y1w0d1E1G1C0d0O0n0Q0|1D0j1d0d0D0!0 0l0z0m0A0*0i011I1s010e0X0E0A0m0u0E1C1*1,1;1K1@1G1`1|0/0a0o0x0j0n0z0n0l0p120A0o0T1(0j0j0E0G2h151 0A1d0N1$2u0d1!1Z1#0Q210*1y0A1_2e1C1n1p0#1J2E0p2G0A1W1o1C0z2n1d2s2u2Y0=1+2i2M1=2R0j0_0B0/0v2r2$0:2#202(1K2*2,0/0i2:1,2=2s2D012`0m2-040k2~2t0;312^0*34360f39302$323f0/0b3i3b3k3d330n2+350/0y3p2?2%1r2_3u2{040C3z3c3C3e3E3w040t3i1e2W152K2x0Q2B320G1W1}1d3U1g3S2!162;053Z0T2X3r3K010R0/0T0e3Q3J2N010L0/0o3{3;3}0A0e0/0A0O0P1@0G1u0E0j0l422@3=0.040K4h3B443^2e2f4e4n324k0g0I3p0o4A413|2)0/0d3i4C431=0n0/0F4H3A320u0p0/0s4z4B4P3s3@040e3u4O4D2_0/0E0B4G3+2 4I4i3}0n3 042P4%4J4)040Q4r0p4t4.2t4X4j0/0c4u3s4R2.5855040w4y520:4B5j4:4o1=4Z0p3`5h5l3l4*0l0d4a0p4c500j5c3}4k4m5h544p044+4-2!4(0*4w5g2Y065k5T5s3s0A4F4`4;4K0/0h4N5r5H1=5a042/5h5S5U5*1K4Z4+0l0E5C1=4k5Q2;5:5U4W5N335Y5)634L045%5Z5m4|485x5z4e4g5G635E5{4|5K6m5O0/0g4V4A5=0*4Z2n0d0q0j14664{3e655R153.0E2u2V6K3T1o3V2x2z2v1V1X2x0m1F6N0N3U0;6!0U0W0Y04.
3. Profondeur

On définit la profondeur d'un dossier comme la longueur maximale d'un chemin menant de ce dossier à un dossier ne contenant pas de sous-dossiers.

La profondeur d'un dossier vide ou ne contenant que des fichiers est donc égale à 0.

Écrire la fonction profondeur qui prend en paramètre un tuple représentant un dossier et renvoie la profondeur de celui-ci.

Exemples
>>> dossier_nsi = ("nsi", [("tp1.py", None), ("tp1.pdf", None)])
>>> profondeur(dossier_nsi)
0
>>> dossier_doc = ("documents", [("photo.jpg", None), dossier_nsi])
>>> profondeur(dossier_doc)
1

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135[tf4)+2r3,sao iug0xm1]P6pnlhe=cy:v(wS/b_dk050Q0E0d0n0q0C0m0p0G0C0n0m0m0F010d0q0A010406050m0r0v0v0n0j0H040M0o0C0r0,0o0B050N0?0^0`0|0;0A04151c051f0N1f1h1c0;0Q0q0J0!0$0(0*0D0q0s0D0C1v0D0d0/050V0O0C0E1q0%0)011u1w1y1w0d1E1G1C0d0O0o0Q0|1D0j1d0d0D0!0 0m0A0n0B0*0i011I1s010e0X0E0B0n0v0E1C1*1,1;1K1@1G1`1|0/0a0p0y0j0o0A0o0m0q120B0p0T1(0j0j0E0G2h151 0B1d0N1$2u0d1!1Z1#0Q210*1y0B1_2e1C1n1p0#1J2E0q2G0B1W1o1C0A2n1d2s2u2Y0=1+2i2M1=2R0j0_0C0/0w2r2$0:2#202(1K2*2,0/0i2:1,2=2s2D012`0n2-040k2~2t0;312^0*34360f39302$323f0/0b3i3b3k3d330o2+350/0z3i1e2W152K2x0Q2B320G1W1}1d3D1g3B2!162;053I0T2X3r1r1K0R0/0T0e3z3c3X0*0L0/0p3%3W2N330e0/2V0o0e130T0r0j3.2@3)010.040K3~2%400B3!2e2f0E3}3Q2 2?463:420g0I3p0p4n3-3(3:48040d3i4p3/1=0o0/0F4v4g320v0q0/0t4m4o4D3s3Z043_4d2Y4w3 4r0/0E0C4u4e2t4S4h4y3+042P4C4q2)490(0q4c4532420c4=3s4F2.4_40420x4l4Z0:4o544#324N0q3$52563s4s0E0m0d0P0Q4a4:4Q3R4,1K4244524L474V4X4}4i0/4k4J55555t4U4t4+4x1K4z044B5b5E2)0O0/0_0u5x1=5q5U2_0/4Y2!5o0*420l5H4T1=4{042/5N5$015K0h5*4$5Y043@3_0B3{5m4f5;5W5s5;5e5w645I5%5z0g5B5c404N2n0d3|145:69335Z3p153T0E2u2V6s3C1o3E2x2z2v1V1X2x0n1F6v0N3D0;6I0U0W0Y04.
4. Contenu

On appelle contenu d'un dossier l'ensemble des sous-dossiers et des fichiers qu'il contient.

De même on appelle chemin entre deux dossiers, le nom des sous-dossiers traversés afin d'accéder du premier au dernier. Le nom du dossier de départ ne fait pas partie du chemin, par contre celui du dossier d'arrivée en fait partie.

Écrire la fonction contenu qui prend en paramètre un tuple représentant un dossier et un chemin menant de ce dossier à un de ses descendants. Cette fonction le contenu du sous-dossier visé par le chemin.

On garantit que le chemin passé en paramètre mène à un sous-dossier existant.

Exemples
>>> dossier_nsi = ("nsi", [("tp1.py", None), ("tp1.pdf", None)])
>>> contenu(dossier_nsi, [])
[("tp1.py", None), ("tp1.pdf", None)]
>>> dossier_doc = ("documents", [("photo.jpg", None), dossier_nsi])
>>> contenu(dossier_doc, ["nsi"])
[("tp1.py", None), ("tp1.pdf", None)]

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135[tf4)+2r3,sa!o iug08m1]P6pnl7he=cy:v(wS/bdk050R0G0d0n0r0D0m0q0I0D0n0m0m0H010d0r0B010406050m0s0w0w0n0j0J040O0p0D0s0-0p0C050P0@0_0{0}0=0B04161d051g0P1g1i1d0=0R0r0L0#0%0)0+0F0r0t0F0D1w0F0d0:050W0Q0D0G1r0(0*011v1x1z1x0d1F1H1D0d0Q0p0R0}1E0j1e0d0F0#100m0B0n0C0+0i011J1t010e0Y0G0C0n0w0G1D1+1-1=1L1^1H1{1}0:0a0q0z0j0p0B0p0m0r130C0q0U1)0j0j0G0I2i16200C1e0P1%2v0d1#1!1$0R220+1z0C1`2f1D1o1q0$1K2F0r2H0C1X1p1D0B2o1e2t2v2Z0?1,2j2N1?2S0j0`0D0:0x2s2%0;2$212)1L2+2-0:0i2;1-2?2t2E012{0n2.040k2 2u0=322_0+35370f3a312%333g0:0b3j3c3l3e340p2,360:0A3q2@2(1s2`3v2|040E3A3d3D3f3F3x040v3j1f2X162L2y0R2C330I1X1~1e3V1h3T2#172=053!0U2Y3s3L010S0:0U0e3R3K2O010N0:0q3|3=3~0C0e0:3!0C0d1`0s432^3?0/040M4e3C453_2f2g0G0j4k334h0l3j423}2*480F0G0w2Q4s3t4h0g0K3q0q4L4x444z041`0e1-0d0m4w3B330p0:0H4W4y2`4n0)0r4q4F4g0:0c4-3~4D2/4;1?4h0y4K4M4X3t3^040e3v4$4O4(4Q0W0B0G544f3~0p40044E3,304N5c4P0I4B4D155i2u4~4.044J5r0;4M5z5k4l4P0r5b5C1L4Z044#5x5B334?040u4|5A5M4 0:0N1v1H5F3m0:4R4T4V5x5t3~4h4:5)4%3f0:5E5.550+4`5-2#5/015O5Q5?5l1L4`5Z3t5I0o5K2Z5T3?0C5#585a605G5^0:5w2Z065S5S5*5D643?5I0h682=6a4=0r4@5x6m6n6p565$4a5(696E0+5I6v5j6K345#465%4^624/6U5:5g6X015_6!5O2:6g4t0:4{6B5z6P502o0d0s0j5q6J5|6c4Q6S6H3A0P3/0G2v2W733U1p3W2y2A2w1W1Y2y0n1G760P3V0=7j0V0X0Z04.