Top -H Option in Macosx

top command in Mac OS X got truncated

First, if you're trying to get the data programmatically, driving top is almost definitely not what you want to do.

But, to answer your direct questions:

how to get the full process name?

There is no way to control the truncation of commands. You can use the -ncols parameter to set the width of the output for non-interactive output, but that doesn't stop top from truncating if it wants to.

sometimes the app icon show next to the process name, is there anyway to do the similar thing using objective-c? should I simply navigate to the app contents folder and grab the icns image?

No. How would you deal with apps that have multiple .icns files, e.g., for document icons? (Try it with iTunes, for example. If you pick the first .icns, you get the AIFF document icon; if you pick the last, you get the internal-use recent TV shows icon.)

The right way to do it is to get the NSBundle for the application, then do something like this:

NSString *iconFile = [bundle objectForInfoDictionaryKey:@"CFBundleIconFile"];
if (iconFile) {
NSString *iconPath = [bundle pathForResource:iconFile ofType:@"icns"];
// load and display the icon
}

So, how do you actually want to do this, if not by driving top?

Well, what you're asking for is actually not a well-defined thing. OS X has four different notions of task/process/program/application that don't correspond 1-to-1, and that makes life difficult if you want to write a mashup of two programs that use different notions—e.g., top deals in BSD processes, while Activity Monitor deals in OS X applications.

If what you actually want is the same list top uses, it's open source, so you can read it and do the same thing it does.

But the simplest way to get the list of BSD processes is probably the interfaces in libproc.h, in particular proc_listallpids and proc_pidinfo. For example:

int dump_proc_names() {
int buf[16384];
int count = proc_listallpids(&buf, 16384*sizeof(int));
for (int i = 0; i != count; ++i) {
int pid = buf[i];
char path[MAXPATHLEN+1] = {0};
int ret = proc_pidinfo(pid, PROC_PIDPATHINFO, 0,
&path, sizeof(path));
if (ret < 0) {
printf("%d: error %s (%d)\n", pid, strerror(errno), errno);
} else {
printf("%d: %s\n", pid, path);
}
}
}

Obviously in real code you're going to want to allocate the buffer dynamically, return the values instead of just dumping them, get more than just the paths, etc. But this is enough to give you the basic idea. (When you go to get additional information, be aware that you if you ask for any struct, you will get an EPERM error unless you have rights to see every member of that struct. So, don't go asking for PROC_PIDTASKALLINFO if you only want PROC_PIDT_SHORTBSDINFO.


Anyway, since this API deals with BSD processes (and Mach tasks), not applications, it won't directly help you get at the NSBundle you want to provide Activity Monitor-style features.

There is no way to do this that's entirely correct, but you can probably get away with something like this:

NSString *path = processPath;
while (path && ![path isEqualTo:@"/"]) {
NSBundle *bundle = [NSBundle bundleWithPath:path];
if (bundle) {
if ([bundle executablePath != processPath]) return nil;
return bundle;
}
path = [path stringByDeletingLastPathComponent];
}

There are probably alternative ways to do this, each with different tradeoffs. For example, using -[NSWorkspace runningApplications], storing the results in a dictionary mapping the bundle executable path to the bundle, and using that to look up each process is simple, but it only seems to be useful for applications owned by the current user (and probably in the current session). On the other hand, enumerating all bundles on the system, or asking Spotlight, or similar would probably be too slow to do on the fly, but would go out of date if you cached them on first run.


Another option, in place of libproc, is to use libtop.

Unfortunately, Apple doesn't provide it. They do have a libtop implementation, which they use for their top tool, but it's actually embedded in the source to top and not available from outside. You can find the source (at the link above) and embed it into your program the same way top itself does.

Alternatively, both GNU and BSD process utilities have Mac ports (although knowing which name to use with Homebrew/MacPorts/Google search isn't always easy…), so you could build one of those and use it.

However, unless you're trying to write cross-platform software (or already know how to write this code for linux or FreeBSD or whatever), I think that just adds extra complexity.

OS X Bash, 'watch' command

You can emulate the basic functionality with the shell loop:

while :; do clear; your_command; sleep 2; done

That will loop forever, clear the screen, run your command, and wait two seconds - the basic watch your_command implementation.

You can take this a step further and create a watch.sh script that can accept your_command and sleep_duration as parameters:

#!/bin/bash
# usage: watch.sh <your_command> <sleep_duration>

while :;
do
clear
date
$1
sleep $2
done

Show human-readable file sizes in OSX terminal

A better answer to this question 2 years on (using Terminal in OSX 10.11) is to simply add -h to the ls command to get human readable file sizes.

To my understanding in later OSX editions, using brew to install coreutils is not required. (If I am wrong, someone correct me.)

For example, to get a list of files in the current directory, as a single column list, and showing file details, enter:

ls -l

If you want human readable file sizes, simply add an "h":

ls -hl

or

ls -lh

The letters after the "-" can be in any order in this instance.

If, as the question detail states, one wants the file list to be ordered by file size, largest file size at the top, then add a capital "S":

ls -lhS

If you want invisible files listed as well then add an "a":

ls -alhS

Again the letters after the "-" can be in any order.


If your creating and editing files in the current directory often, perhaps because you are in the process of working on a task or project, an alternative combination is:

ls -hltur

This lists files in human readable file size format, in a long list down the Terminal window.

The "t" instructs the sort order of the files by their last modified date/times.

The "u" then alters this slightly to use the time the files were last accessed, rather than last modified.

The "r" then reverse the order of the list so that the more recently accessed or 'touched' files are listed last, at the bottom of the list.

The full combination means that you have a detailed list, with the files that you have read, opened or modified most recently, or been 'touched' similarly by a process you have run or another process, all at the bottom of the list.

Hence even if the list in your current directory is long such that the beginning of the list can no longer be read without scrolling up, the files you have interacted with will likely remain visible immediately above your next, ready to type in, command line.

These options, and more, are in the man (manual) page for the ls command:

man ls

If you want to list files regularly in one of the above formats, or another of your choice upon reading the man page, you can add an alias to your .bash_profile file, (eg using nano to open this file, and doing so while you are in your home directory).

For example, to fulfill that desired by the original poster of the question, open the file and on a fresh line add:

alias lss='ls -hlS'

Then, upon saving the file and exiting that Terminal window and opening a new Terminal window, typing "lss" in the command line should provide that which you seek routinely when listing files.

If you do not know how to use nano, first bring up its man(ual) page by typing

man nano

The man page will explain how to use nano.

To exit a man page and get back to where you can enter a command, press the key "q".

head command to skip last few lines of file on MAC OSX

Use awk for example:

$ cat file
line 1
line 2
line 3
line 4
line 5
line 6
$ awk 'n>=4 { print a[n%4] } { a[n%4]=$0; n=n+1 }' file
line 1
line 2
$

It can be simplified to awk 'n>=4 { print a[n%4] } { a[n++%4]=$0 }' but I'm not sure if all awk implementations support it.

How can I clear previous output in Terminal in Mac OS X?

To clear the terminal manually:

+K

Command+K for newer keyboards

To clear the terminal from within a shell script;

/usr/bin/osascript -e 'tell application "System Events" to tell process "Terminal" to keystroke "k" using command down'


Related Topics



Leave a reply



Submit