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

.128013rv56be:olg1ma(cd tu4S2hwspk]=3/_P[iyn)+f050q0g0s0n0J0j0z0r0p0j0n0z0z0D010s0J0A010406050z0t0m0m0n0b0K040v0i0j0t0)0i0L050F0:0=0@0_0.0A041219051c0F1c1e190.0q0J0c0X0Z0#0%0x0J0k0x0j1s0x0s0,050S0f0j0g1n0!0$011r1t1v1t0s1B1D1z0s0f0i0q0_1A0b1a0s0x0X0|0z0A0n0L0%0w011F1p010O0U0g0L0n0m0g1z1%1)1.1H1;1D1@1_0,0a0r0H0b0i0A0i0z0J0 0L0r0Q1#0b0b0g0p2e121|0L1a0F1Z2r0s1X1W1Y0q1~0%1v0L1?2b1z1k1m0Y1G2B0J2D0L1T1l1z0A2k1a2p2r2V0/1(2f2J1/2O0b0?0j0,0l2o2Z0-2Y1}2#1H2%2)0,0w2-1)2/2p2A012@0n2*040E2{2q0.2~2=0%31330u362}2Z2 3c0,0d3f383h3a300i2(320,0e3f1b2T122H2u0q2y2 0p1T1`1a3A1d3y2X132.053F0Q2U3o1o1H0B0,0Q0O3w393U0%0y0,0r3!3T2K300O0,0L0f0G0q2b2c0g0b0z3+2;3$010+040o3}2!3 0L3X3^0J3`442 410M0h3m0r4i3*3#3-47040s3f4k3,1/0i0,0D4q2:453-0m0J2+4h4j4y2 3W040O3r4x4l2$0,0g0j4p3N2|4r3~3-0i3(042M4M4s2?480#4a0b4c3p410I4-3 4B4D4T2q4G4.0,0C4g4^0-4j514V4z1/4I0J3Z4 533i4P0z0s3?494b4 4`3 41435i4N4(044Q4S2X5o0%4e4~2V06525A5a3p4n5s2.5C3 4u040N4w595j4m3:3=3@4*3`3|5n4%5v0,5m5t5X304P4R4;3-4e4E4i5O550,2k0s0t0b115N5u5%4o3m123Q0g2r2S613z1l3B2u2w2s1S1U2u0n1C640F3A0.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

.128013rv568be:olg1ma(cd7 tu4S2hwspk]=30/_P[iyn)+f050r0h0u0o0M0k0B0t0q0k0o0B0B0F010u0M0C010406050B0v0n0n0o0b0N040x0j0k0v0,0j0O050I0?0^0`0|0;0C04151c051f0I1f1h1c0;0r0M0c0!0$0(0*0z0M0l0z0k1v0z0u0/050V0g0k0h1q0%0)011u1w1y1w0u1E1G1C0u0g0j0r0|1D0b1d0u0z0!0 0B0C0o0O0*0y011I1s010R0X0h0O0o0n0h1C1*1,1;1K1@1G1`1|0/0a0t0K0b0j0C0j0B0M120O0t0T1(0b0b0h0q2h151 0O1d0I1$2u0u1!1Z1#0r210*1y0O1_2e1C1n1p0#1J2E0M2G0O1W1o1C0C2n1d2s2u2Y0=1+2i2M1=2R0b0_0k0/0m2r2$0:2#202(1K2*2,0/0y2:1,2=2s2D012`0o2-040G2~2t0;312^0*34360w39302$323f0/0d3i3b3k3d330j2+350/0e3p2?2%1r2_3u2{040s3z3c3C3e3E3w040f3i1e2W152K2x0r2B320q1W1}1d3U1g3S2!162;053Z0T2X3r3K010D0/0T0R3Q3J2N010A0/0t3{3;3}0O0R0/0O0g0J1@0q1u0h0b0B422@3=0.040p4h3B443^2e2f4e4n324k0P0i3p0t4A413|2)0/0u3i4C431=0j0/0F4H3A320n0M0/0H4z4B4P3s3@040R3u4O4D2_0/0h0k4G3+2 4I4i3}0j3 042P4%4J4)040r4r0M4t4.2t4X4j0/0L4u3s4R2.5855040E4y520:4B5j4:4o1=4Z0M3`5h5l3l4*0B0u4a0M4c500b5c3}4k4m5h544p044+4-2!4(0*4w5g2Y065k5T5s3s0O4F4`4;4K0/0Q4N5r5H1=5a042/5h5S5U5*1K4Z4+0B0h5C1=4k5Q2;5:5U4W5N335Y5)634L045%5Z5m4|485x5z4e4g5G635E5{4|5K6m5O0/0P4V4A5=0*4Z2n0u0v0b14664{3e655R153.0h2u2V6K3T1o3V2x2z2v1V1X2x0o1F6N0I3U0;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

.128013rv56be:olg1ma(cd tu4S2hwspk]=30/[P_,ixyn)+f050q0g0s0n0L0j0z0r0p0j0n0z0z0D010s0L0A010406050z0t0m0m0n0b0N040v0i0j0t0,0i0O050G0?0^0`0|0;0A04151c051f0G1f1h1c0;0q0L0c0!0$0(0*0x0L0k0x0j1v0x0s0/050V0f0j0g1q0%0)011u1w1y1w0s1E1G1C0s0f0i0q0|1D0b1d0s0x0!0 0z0A0n0O0*0w011I1s010R0X0g0O0n0m0g1C1*1,1;1K1@1G1`1|0/0a0r0I0b0i0A0i0z0L120O0r0T1(0b0b0g0p2h151 0O1d0G1$2u0s1!1Z1#0q210*1y0O1_2e1C1n1p0#1J2E0L2G0O1W1o1C0A2n1d2s2u2Y0=1+2i2M1=2R0b0_0j0/0l2r2$0:2#202(1K2*2,0/0w2:1,2=2s2D012`0n2-040E2~2t0;312^0*34360u39302$323f0/0d3i3b3k3d330i2+350/0e3i1e2W152K2x0q2B320p1W1}1d3D1g3B2!162;053I0T2X3r1r1K0B0/0T0R3z3c3X0*0y0/0r3%3W2N330R0/2V0i0R130T0t0b3.2@3)010.040o3~2%400O3!2e2f0g3}3Q2 2?463:420P0h3p0r4n3-3(3:48040s3i4p3/1=0i0/0D4v4g320m0L0/0F4m4o4D3s3Z043_4d2Y4w3 4r0/0g0j4u4e2t4S4h4y3+042P4C4q2)490(0L4c4532420H4=3s4F2.4_40420C4l4Z0:4o544#324N0L3$52563s4s0g0z0s0J0q4a4:4Q3R4,1K4244524L474V4X4}4i0/4k4J55555t4U4t4+4x1K4z044B5b5E2)0f0/0_0M5x1=5q5U2_0/4Y2!5o0*420K5H4T1=4{042/5N5$015K0Q5*4$5Y043@3_0O3{5m4f5;5W5s5;5e5w645I5%5z0P5B5c404N2n0s3|145:69335Z3p153T0g2u2V6s3C1o3E2x2z2v1V1X2x0n1F6v0G3D0;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

.128013rv568be:olg1ma(cd7 tu4S2hwspk]=!30/[P,iyn)+f050r0h0u0o0N0k0B0t0q0k0o0B0B0F010u0N0C010406050B0v0n0n0o0b0O040x0j0k0v0-0j0P050J0@0_0{0}0=0C04161d051g0J1g1i1d0=0r0N0c0#0%0)0+0z0N0l0z0k1w0z0u0:050W0g0k0h1r0(0*011v1x1z1x0u1F1H1D0u0g0j0r0}1E0b1e0u0z0#100B0C0o0P0+0y011J1t010S0Y0h0P0o0n0h1D1+1-1=1L1^1H1{1}0:0a0t0L0b0j0C0j0B0N130P0t0U1)0b0b0h0q2i16200P1e0J1%2v0u1#1!1$0r220+1z0P1`2f1D1o1q0$1K2F0N2H0P1X1p1D0C2o1e2t2v2Z0?1,2j2N1?2S0b0`0k0:0m2s2%0;2$212)1L2+2-0:0y2;1-2?2t2E012{0o2.040H2 2u0=322_0+35370w3a312%333g0:0d3j3c3l3e340j2,360:0e3q2@2(1s2`3v2|040s3A3d3D3f3F3x040f3j1f2X162L2y0r2C330q1X1~1e3V1h3T2#172=053!0U2Y3s3L010D0:0U0S3R3K2O010A0:0t3|3=3~0P0S0:3!0P0u1`0v432^3?0/040p4e3C453_2f2g0h0b4k334h0M3j423}2*480z0h0n2Q4s3t4h0Q0i3q0t4L4x444z041`0S1-0u0B4w3B330j0:0F4W4y2`4n0)0N4q4F4g0:0K4-3~4D2/4;1?4h0E4K4M4X3t3^040S3v4$4O4(4Q0W0C0h544f3~0j40044E3,304N5c4P0q4B4D155i2u4~4.044J5r0;4M5z5k4l4P0N5b5C1L4Z044#5x5B334?040I4|5A5M4 0:0A1v1H5F3m0:4R4T4V5x5t3~4h4:5)4%3f0:5E5.550+4`5-2#5/015O5Q5?5l1L4`5Z3t5I0G5K2Z5T3?0P5#585a605G5^0:5w2Z065S5S5*5D643?5I0R682=6a4=0N4@5x6m6n6p565$4a5(696E0+5I6v5j6K345#465%4^624/6U5:5g6X015_6!5O2:6g4t0:4{6B5z6P502o0u0v0b5q6J5|6c4Q6S6H3A0J3/0h2v2W733U1p3W2y2A2w1W1Y2y0o1G760J3V0=7j0V0X0Z04.