You can make a difference in the Apple Support Community!

When you sign up with your Apple Account, you can provide valuable feedback to other community members by upvoting helpful replies and User Tips.

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Using dictionary from command line

Is it possible I could see the definition of a word for eg. 'Apple' in terminal itself without opening the dictionary app?

I work in the terminal most of the times and I am just wondering if I could get all the information in terminal itself.

Any ideas? Thanks!

Message was edited by: kt.kthapar

iMac 27' Quadcore, Mac OS X (10.6.4)

Posted on Dec 11, 2010 6:04 AM

Reply
Question marked as Top-ranking reply

Posted on Dec 12, 2010 2:56 PM

Linc Davis wrote:
you could install the POSIX 'dict' command (e.g. from MacPorts) which is a client for online dictionaries.


Ugh! How crude!

The suggestion given above launches Dictionary.app, which is apparently not what you want.


Yes indeed. Sorry for not paying more attention.

Since you work in terminal most of the time, a little Xcode can't hurt.
1) Create a new Foundation Command Line Tool in Xcode.
2) Replace the lines:

// insert code here...
NSLog(@"Hello, World!");

with

if(argc < 2)
{
printf("Usage: dict <word to define> ");

return -1;
}

NSString * search =
[NSString stringWithCString: argv[1] encoding: NSUTF8StringEncoding];

CFStringRef def =
DCSCopyTextDefinition(NULL,
(CFStringRef)search,
CFRangeMake(0, [search length]));

NSString * output =
[NSString
stringWithFormat:
@"Definition of <%@>: %@", search, (NSString *)def];

printf("%s", [output UTF8String]);

3) Add the CoreServices framework to the project. Right/command click on "External Frameworks and Libraries", choose "Add..", choose "Existing Frameworks..", choose "CoreServices.framework", and click "Add".
4) Build
5) Enjoy
40 replies
Question marked as Top-ranking reply

Dec 12, 2010 2:56 PM in response to Linc Davis

Linc Davis wrote:
you could install the POSIX 'dict' command (e.g. from MacPorts) which is a client for online dictionaries.


Ugh! How crude!

The suggestion given above launches Dictionary.app, which is apparently not what you want.


Yes indeed. Sorry for not paying more attention.

Since you work in terminal most of the time, a little Xcode can't hurt.
1) Create a new Foundation Command Line Tool in Xcode.
2) Replace the lines:

// insert code here...
NSLog(@"Hello, World!");

with

if(argc < 2)
{
printf("Usage: dict <word to define> ");

return -1;
}

NSString * search =
[NSString stringWithCString: argv[1] encoding: NSUTF8StringEncoding];

CFStringRef def =
DCSCopyTextDefinition(NULL,
(CFStringRef)search,
CFRangeMake(0, [search length]));

NSString * output =
[NSString
stringWithFormat:
@"Definition of <%@>: %@", search, (NSString *)def];

printf("%s", [output UTF8String]);

3) Add the CoreServices framework to the project. Right/command click on "External Frameworks and Libraries", choose "Add..", choose "Existing Frameworks..", choose "CoreServices.framework", and click "Add".
4) Build
5) Enjoy

Mar 23, 2014 5:26 PM in response to kt.kthapar

One could put the following code in their ~/.bashrc file as a shell function.


dict () {

curl dict://dict.org/d:"${1}"

}


Then:


source .bashrc

dict Apple | more


Alternative using SpotLight


Use command+Space will open Spotlight. Put in the word you want to look up in the Apple Dictionary App. The results appear far down on the Spotlight results. Press command+L to jump to the dictionary entry and open the result in a Window, or command+D to open the Apple Dictionary App referencing the Spotlight word.

Oct 31, 2015 11:53 AM in response to kt.kthapar

Copy and paste the following Python script as plain text into a new TextEdit document. Save it as dict.py to your Scripts folder located at /Users/<username>/Library/Scripts/. Adjust the textwrap column width (width=76), and the initial_indent and subsequent_indent spacings to your preference:

#!/usr/bin/env python2.7 import sys import DictionaryServices import textwrap def main(): try: search_term = sys.argv[1] except IndexError: print 'No search term was entered.' sys.exit() search_result = DictionaryServices.DCSCopyTextDefinition( None, search_term, (0, len(search_term))) if not search_result: print '"%s" was not found in Dictionary.' % (search_term) else: term_definition = search_result.replace( u'\u25B6', '').replace('ORIGIN', ' ORIGIN') single_spacing = ' '.join(term_definition.split()) wrapper = textwrap.TextWrapper(width=76, initial_indent=' ', subsequent_indent=' ') print wrapper.fill(single_spacing) if __name__ == '__main__': main()


Make the script executable with the following command in Terminal, substituting your username for <username>:

chmod u+x /Users/<username>/Library/Scripts/dict.py


If using the default bash shell in Terminal, place the following line in your ~/.bash_profile, substituting your username for <username>. If using a different shell, such a zsh, place it in that shell's profile. For zsh that would be ~/.zprofile:

alias dict='/Users/<username>/Library/Scripts/dict.py'


Then simply use the "dict" command with the search term you wish defined.

User uploaded file

If you prefer, use the following Python script to display the definition in a border. Adjust the textwrap column width (width=76) to your preference and the border will resize automatically:

#!/usr/bin/env python2.7 import sys import DictionaryServices import textwrap def main(): try: search_term = sys.argv[1] except IndexError: print 'No search term was entered.' sys.exit() search_result = DictionaryServices.DCSCopyTextDefinition( None, search_term, (0, len(search_term))) if not search_result: print '"%s" was not found in Dictionary.' % (search_term) else: term_definition = search_result.replace( u'\u25B6', '').replace('ORIGIN', ' ORIGIN') single_spacing = ' '.join(term_definition.split()) border_text = textwrap.fill(single_spacing, width=76).splitlines() max_length = max(len(s) for s in border_text) column_width = max_length + 2 print '+' + '-' * column_width + '+' for s in border_text: print '| %-*.*s |' % (max_length, max_length, s) print '+' + '-' * column_width + '+' if __name__ == '__main__': main()

User uploaded file

The elapsed time to return a definition is acceptable, generally less than a third of a second (on my 2008 MacBook Pro).

User uploaded file

Nov 1, 2015 7:02 AM in response to Roote

I have posted Python and Ruby code to the communities in the past, that was syntax, format, and runtime correct on my end. In the support communities, I have used plain text (posting directly into the article), placed the code within an inserted quote, or various syntax highlighting choices from the advanced editor, and the code did not remain true to the same format as it was on my Mac.


The following Python code contains no tabs, and all indented code is in 4-space multiples. This was done as an exercise to see if you can copy/paste it back to you, and run it without indentation errors. The code when provided a full, or shorthand path to a Word .docx document, will list the fonts that are referenced inside of it. It uses a positive Lookbehind in the regular expression. It is tested on El Capitan 10.11.1, and the default Python 2.7.10 from Apple. I never post code that uses a third-party Python module.

User uploaded fileUser uploaded file


#!/usr/bin/env python

import zipfile

import re

import os

import sys




def main():

fonts = []

try:

thefile = os.path.expanduser(sys.argv[1])

except (ValueError, IndexError):

sys.exit('Usage: {} filename.docx\n'.format(sys.argv[0]))

if not thefile.endswith('.docx'):

sys.exit('Not a valid Word document')

# Word docx compressed-zip, single file format

if zipfile.is_zipfile(thefile):

with zipfile.ZipFile(thefile, 'r') as pzip:

xmldata = pzip.read('word/fontTable.xml')

fonts = re.findall(r'(?<=w:name=)("[ \w+]+")>', xmldata)

for name in fonts:

print("{}".format(name))

if __name__ == '__main__':

sys.exit(main())


Nov 2, 2015 10:45 AM in response to VikingOSX

Sublime Text is an excellent tool, especially for indentation dependent code. Thanks for the tip regarding tabs to spaces, a nice time saver. Here's dict.py and dictbox.py in Sublime Text:

User uploaded file User uploaded file

I suppose an option, given the code sharing vagaries of the hosting service, is to use a file sharing service to provide a download link. With that in mind, here are Dropbox links for previewing the code and downloading:


dict.py

dictbox.py

User uploaded file

User uploaded file

Tested with:


OS X El Capitan 10.11, Python 2.7.10

OS X Yosemite 10.10.5, Python 2.7.10

OS X Mavericks 10.9.5, Python 2.7.5

Nov 8, 2015 10:45 PM in response to KcidKcus

Hi KcidKcus. You're welcome; I glad you found the script(s) useful. I posted revised versions of dict.py and dictbox.py with the same links which you may want to download. They fix some indenting and support for accented letters. No need to revise your ~/.bash_profile, just replace dict.py or dictbox.py in your Scripts folder. Btw, for search terms other than single or hyphenated, use double quotes ("") or escape using the backslash (\). If you copy and paste, a phrase for example, you can paste with the Control-Command-V keys to paste escaped text. Some examples:

User uploaded file

May 22, 2017 8:45 PM in response to Roote

Tangentially, if you like to discover new words, you can look up words randomly in Dictionary on the command-line using dict.py, described in a previous post above, and command substitution. You'll first need to extract a word list from whichever dictionary you use. You can then use a language and function of your choice. I prefer shuf, non-native to OS X, but which you can download as part of GNU Coreutils. You can also use Ruby, Perl, or Python which are all included in OS X.


Shuf:


dict "$(shuf -n1 ~/WordLists/NOAD3rdED.txt)"


Ruby:


dict "$(ruby -e 'puts $<.readlines.shuffle' < ~/WordLists/NOAD3rdED.txt | sed -n 1,1p)"


Perl:


dict "$(perl -MList::Util=shuffle -e 'print shuffle <>' ~/WordLists/NOAD3rdED.txt | head -1)"


Python:


dict "$(python -c 'import random, sys; print random.choice(open(sys.argv[1]).readlines()),' ~/WordLists/NOAD3rdED.txt)"


If you create a shell script and name it something like dictrand.sh, and place an alias in your ~/.bash_profile as described in a previous post above for dict, you can just use the command name. A script example:


#!/bin/bash


/Users/pd/Library/Scripts/dict.py "$(shuf -n1 ~/WordLists/NOAD3rdED.txt)"


Line example in ~/.bash_profile:


alias dictrand='/Users/pd/Library/Scripts/dictrand.sh'

User uploaded file

Nov 4, 2015 2:07 PM in response to VikingOSX

Hello VikingOSX,


Thank you for testing it. It is indeed very good news that manual loading of bridgesupport metadata still works with recent pyobjc, for it opens straightforward door to undocumented framework functions without resorting to ctypes module.


Regarding DictionaryServices.framework, more comlpicated and finer queries are possible by using undocumented functions as shown in the following threads. Now those rubycocoa codes may be translated into pyobjc codes without much difficulty.


How can I use Automator to extract substring of text based on pattern?

https://discussions.apple.com/thread/6525478


Results from OpenThesaurus as a Service: How?

https://discussions.apple.com/thread/6616776



---

By the way, here's a revision of my script which incorporated textwrap feature inspired by Roote. 🙂



#!/usr/bin/python # coding: utf-8 # # file: # dict.py # # usage: # ./dict.py hippopotamus rhinoceros 人 佛 # # version: # 0.20 # - added textwrap feature # 0.15 # - manually loading fixed bridgesupport metadata # # written by Hiroto, 2015-11 # import sys, objc import textwrap from CoreFoundation import * DCS_BRIDGESUPPORT = '''<?xml version="1.0" standalone="yes"?> <!DOCTYPE signatures SYSTEM "file://localhost/System/Library/DTDs/BridgeSupport.dtd"> <signatures version="0.9"> <function name="DCSCopyTextDefinition"> <arg type="^{__DCSDictionary=}"></arg> <arg type="^{__CFString=}"></arg> <arg type64="{_CFRange=qq}" type="{_CFRange=ii}"></arg> <retval type="^{__CFString=}"></retval> </function> </signatures>''' objc.parseBridgeSupport( DCS_BRIDGESUPPORT, globals(), objc.pathForFramework('/System/Library/Frameworks/CoreServices.framework/Frameworks/DictionaryServices.framework') ) for q in [ e.decode('utf-8') for e in sys.argv[1:] ]: r = DCSCopyTextDefinition(None, q, (0, len(q))) or 'nil' r = ' '.join(r.split()) r = textwrap.fill(r, width=48) print '[%s]\n%s\n' % tuple( [e.encode('utf-8') for e in [q, r]] )




All the best,

Hiroto

Mar 22, 2014 8:39 PM in response to etresoft

Thanks for the great ObjC code.


  • `CFRelease(def);` should be added at the end to release the string returned by `DCSCopyTextDefinition()`.
  • As of Xcode 5.1 on OS X 10.9.2 with ARC you also need `__bridge` cast qualifiers: `

(__bridgeCFStringRef)` and `(__bridgeNSString*)`.

Also, adding the CoreServices framework (in addition to Foundation) appears not to be necessary.

`

Using dictionary from command line

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.