-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathls_al.py
More file actions
executable file
·161 lines (136 loc) · 5.2 KB
/
ls_al.py
File metadata and controls
executable file
·161 lines (136 loc) · 5.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env python3
"""This Python script replicates the functionality of ls -al on macOS. Here's what it does:
"v001 + new :ls_al.py & README.md"
total 64
drwxr-xr-x 3 username staff 96 Dec 7 10:30 .
drwxr-xr-x 15 username staff 480 Dec 6 14:22 ..
-rw-r--r-- 1 username staff 1234 Dec 7 09:15 file.txt
Code generated by Claude handles edge cases like permission errors, missing files, and
symbolic links, making it a robust replacement for the native ls -al command.
Usage:
bashpython3 ls_al.py # List current directory
python3 ls_al.py /path/to/dir # List specific directory
python3 ls_al.py dir1 dir2 # List multiple directories
Key Features:
* Lists all files including hidden ones (starting with .)
* Shows file permissions in the familiar format (e.g., drwxr-xr-x)
* Displays owner and group names
* Shows file sizes, modification times, and link counts
* Handles symbolic links by showing the target
* Includes the total block count at the top
* Supports multiple directory arguments
"""
import os
import stat
import pwd
import grp
import time
import sys
from pathlib import Path
def format_permissions(mode):
"""Convert file mode to permission string like 'drwxr-xr-x'"""
perms = []
# File type
if stat.S_ISDIR(mode):
perms.append('d')
elif stat.S_ISLNK(mode):
perms.append('l')
else:
perms.append('-')
# Owner permissions
perms.append('r' if mode & stat.S_IRUSR else '-')
perms.append('w' if mode & stat.S_IWUSR else '-')
perms.append('x' if mode & stat.S_IXUSR else '-')
# Group permissions
perms.append('r' if mode & stat.S_IRGRP else '-')
perms.append('w' if mode & stat.S_IWGRP else '-')
perms.append('x' if mode & stat.S_IXGRP else '-')
# Other permissions
perms.append('r' if mode & stat.S_IROTH else '-')
perms.append('w' if mode & stat.S_IWOTH else '-')
perms.append('x' if mode & stat.S_IXOTH else '-')
return ''.join(perms)
def format_size(size):
"""Format file size for display"""
return str(size).rjust(8)
def format_time(timestamp):
"""Format modification time like ls -al"""
file_time = time.localtime(timestamp)
current_time = time.localtime()
# If file is from this year, show month/day/time
# Otherwise show month/day/year
if file_time.tm_year == current_time.tm_year:
return time.strftime("%b %d %H:%M", file_time)
else:
return time.strftime("%b %d %Y", file_time)
def get_username(uid):
"""Get username from UID"""
try:
return pwd.getpwuid(uid).pw_name
except KeyError:
return str(uid)
def get_groupname(gid):
"""Get group name from GID"""
try:
return grp.getgrgid(gid).gr_name
except KeyError:
return str(gid)
def ls_al(directory='.'):
"""List files in ls -al format"""
try:
path = Path(directory)
if not path.exists():
print(f"ls: {directory}: No such file or directory")
return
if path.is_file():
# If it's a single file, just list that file
entries = [path]
else:
# List all entries including hidden ones
entries = sorted(path.iterdir(), key=lambda x: x.name.lower())
# Add . and .. entries for directories
entries = [path / '.', path / '..'] + entries
# Calculate total blocks (approximation)
total_blocks = 0
valid_entries = []
for entry in entries:
try:
stat_info = entry.stat()
total_blocks += stat_info.st_blocks
valid_entries.append((entry, stat_info))
except (OSError, PermissionError):
# Skip files we can't stat
continue
print(f"total {total_blocks // 2}") # Convert 512-byte blocks to 1024-byte blocks
for entry, stat_info in valid_entries:
# Format each component
permissions = format_permissions(stat_info.st_mode)
links = str(stat_info.st_nlink).rjust(3)
owner = get_username(stat_info.st_uid).ljust(8)
group = get_groupname(stat_info.st_gid).ljust(8)
size = format_size(stat_info.st_size)
mod_time = format_time(stat_info.st_mtime)
name = entry.name
# Handle symbolic links
if stat.S_ISLNK(stat_info.st_mode):
try:
target = os.readlink(entry)
name = f"{name} -> {target}"
except OSError:
pass
print(f"{permissions} {links} {owner} {group} {size} {mod_time} {name}")
except PermissionError:
print(f"ls: {directory}: Permission denied")
except Exception as e:
print(f"ls: {directory}: {e}")
if __name__ == "__main__":
# Handle command line arguments
if len(sys.argv) > 1:
for directory in sys.argv[1:]:
if len(sys.argv) > 2:
print(f"{directory}:")
ls_al(directory)
if len(sys.argv) > 2:
print()
else:
ls_al()