Giter VIP home page Giter VIP logo

rnm's Introduction

Build Status

Renames files/directories in bulk. Naming scheme (*Name String*) can be applied or regex replace can be performed to modify file names on the fly. It uses PCRE2 (revised version of PCRE) regex to provide search (and replace) functionality.

It provides versatile options to modify names, delete/replace part of it, indexing, case conversion, insert text, insert various file information like modification time, access time, permission etc.., insert parent directory names, working directory name etc.. and many more.

File search functionality is provided with PCRE2 regex. Fixed string search is also possible.

Operations (rename, changing names, search) are selective of file type (directory, file, link).

Files can be sorted by name, modification time, access time, size, file type (directory, file, link) etc..

It provides an undo functionality to move back unwanted rename operations. Different rnm operation on different directory remembers their own undo history.

Simulations can be run instead of actual rename to view the potential outcome as program output on terminal with the -sim option.

Features at a glance:

  1. Rename files/directories/links en masse with dynamically constructed names.
  2. Undo rename.
  3. Names (or name strings) can be taken from a file.
  4. Inserting file information (mtime, atime, ctime, permission etc..) in arbitrary formats.
  5. Indexing and formatting the indexes in different ways.
  6. Latin, scientific and base conversion for indexes and counters.
  7. Inserting different level of parent directory names.
  8. Access to current directory name, file name with and without extension.
  9. Regex replace to delete/swap/replace part of the file name.
  10. A regex replace operation can be performed on file only, directory only, link only or any combination of them.
  11. Uppercase/Lowercase conversion on file name (can be done by selecting a part).
  12. Replace strings can be taken from files.
  13. Search string to search for files with matching regex/string.
  14. Search string can be specified for only file, directory, link or any combination of them.
  15. Inverse search.
  16. Search strings can be taken from files.
  17. Sorting files and indexing.
  18. Sorting files according to size, modification time, access time etc..
  19. Prioritize file, directory or link during sort.
  20. Running simulation.

New features:

  1. Unlimited precision for numbers i.e you can perform base conversion, scientific conversion etc.. on an arbitrarily big number. This functionality is provided by GMP BigNum library (GNU Multi-precession library).
  2. File information is available, e.g modification time, access time, status change time (time string can be formatted using format string e.g %d-%m-%Y), permission, owner id, group id, size, block, inode number, mode etc...
  3. Inverse search is possible.
  4. Each regex operation can be associated with either link, file or directory, for example, if a replace string is associated with only file, it will not work on directories or links.
  5. New sorting methods:
  6. Sort according to file modification time (recent first).
  7. Sort according to file access time (recent first).
  8. Sort according to file status change time (recent first).
  9. Sort according to file size (larger first).
  10. Prioritize directory when sorting.
  11. Prioritize file when sorting.
  12. Prioritize link when sorting.
  13. Reverse sort (can be used to reverse the order of a previous sort).

Install:

For Ubuntu and derivatives:

You can install it in Ubuntu from neurobin PPA (ppa:neurobin/ppa).

sudo add-apt-repository -y ppa:neurobin/ppa
sudo apt-get update
sudo apt-get install rnm

If you are in precise (12.04), you will need to add ubuntu-toolchain repository to make libstdc++6 (>=4.8.4) available:

sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo add-apt-repository -y ppa:neurobin/ppa
sudo apt-get update
sudo apt-get install rnm

For Archlinux:

Install from AUR:

git clone https://aur.archlinux.org/rnm.git
cd rnm
makepkg -i

Using Homebrew (MacOS) or Linuxbrew (Any Linux distro):

Install from neurobin/pkg/rnm with brew:

brew install neurobin/pkg/rnm

From pre-built binaries:

You can download a pre-built binary (64 bit, 32 bit, ppc64el) from the release page if available. These pre-built binaries depend on libstdc++6 >= 4.8.4 if not specified otherwise.

From source:

Make sure you have a C++ compiler equivalent to GCC-4.8 (g++-4.8) or later installed on your system.

Download dependencies:

It depends on three different libraries:

  1. pcre2
  2. jpcre2
  3. gmplib

To install dependencies run the prepare.sh file:

cd rnm # i.e go inside the rnm project directory
#Creating the following directories will prevent prepare.sh from installing the corresponding libraries.
#mkdir -p gmpxx  # uncomment and run this command if libgmp-dev (gmpxx) is already installed.
#mkdir -p pcre2  # uncomment and run this command if libpcre2-dev (pcre2) is already installed.
#mkdir -p jpcre2 # uncomment and run this command if libjpcre2-dev (jpcre2) is already installed.
sh prepare.sh

Install rnm:

After you have all the dependencies at hand, you can simply do:

autoreconf -f -i #run this one if your automake version is less than 1.15
./configure --prefix=/usr
make
sudo make install

Uninstall:

  1. For Debian, Ubuntu and derivatives, uninstall from software manager.
  2. For Archlinux, uninstall with pacman.
  3. For MacOS, uninstall with brew uninstall rnm
  4. If you used a pre-built binary, just delete the binary and the man page.
  5. If you compiled from the source, do ./configure --prefix=/usr && make && sudo make uninstall

Basic options

  • -ns: Name string, simply new name for files. String wrapped with / are treated as special rules and expanded to their special meaning.
  • -rs: Replace string. Performs regex replace to construct new name.
  • -ss: Searches files with matching regex.
  • -ssf: Searches files with matching fixed string.
  • -s: Sort files.
  • -fo: File only mode.
  • -do: Directory only mode.
  • -lo: Link only mode.
  • -dp: Depth of directories (how many subdirs to recurse).
  • -u: Undo the last rename operation in the current directory.
  • -up: Undo rename from an arbitrary undo path.
  • -ups: Show available undo paths.
  • -duh: Delete undo history older than the given seconds.
  • -duhd: Delete undo history older than the given days.

For a complete list of options and to get a glimpse of what rnm is capable of, get a peek at the doc (rnm.md or rnm.html) or man page (man rnm).

# Usage:

Simplest example:

rnm -ns newname oldfile
#rename by adding something to oldname:
rnm -ns '/fn/ some text to add' oldfile

/fn/ is a name string rule that expands to file name.

Indexing

Rename all by appending index to file names:

rnm -ns '/n/ /i/./e/' ./* -dp -1
Before After
file.mp3 file 1.mp3
song.mp3 song 2.mp3
video/song.mp4 video/song 3.mp4

/n/ is a name string rule which expands to file name without extension of the current renaming file. /e/ is a name string rule which expands to file extension. /i/ is another name string rule which expands to index. -dp -1 means unlimited depth i.e go to all subdirs.

Rename all by appending directory wise index to file names:

rnm -ns '/n/ /id/./e/' ./* -dp -1
Before After
dir1/file.mp3 dir1/file 1.mp3
dir1/song.mp3 dir1/song 2.mp3
dir2/file.mp3 dir2/file 1.mp3
dir2/song.mp3 dir2/song 2.mp3

/id/ is a name string rule which expands to directory index (index inside directory).

Index with leading zeros ( file 001, 002 etc..):

rnm -ns '/n/ /id/./e/' -ifl 4 ./*
Before After
file.mp3 file 0001.mp3
song.mp3 song 0002.mp3
... ...
video.mp4 video 0010.mp4

-ifl 4 sets index field length to 4 and thus remaining space is filled with 0 (by default).

Use custom increment value:

rnm -ns '/n/ /id/./e/' -ifl 2 -inc 4 ./*
Before After
file.mp3 file 01.mp3
song.mp3 song 05.mp3

-inc 4 sets the index increment value to 4.

Decreasing index:

rnm -ns '/n/ /-id/./e/' -ifl 3 -inc 4 ./*
Before After
file.mp3 file -001.mp3
song.mp3 song -005.mp3

-inc is always positive, but decremented index can be accessed by appending - in (at beginning) them.

Set starting index:

rnm -ns '/n/ /id/./e/' -ifl 3 -inc 4 -si 4 ./*
Before After
file.mp3 file 004.mp3
song.mp3 song 008.mp3

There are lots of magics you can do with index, like converting to binary, octal, hexadecimal etc.., converting to scientific or latin number, use index flags to manipulate their format etc.. Refer to the doc (rnm.md or rnm.html) or man page (man rnm) for complete details.

Change/Modify/remove part of a file name

rnm uses PCRE2 regex to provide regex replace on old filename. The general format for regex replace:

'/regex/replace/modifier'

where regex is the regex to match in the file name, replace is the string to replace the match with and modifiers are : g (global) i (case insensitive), d (directory), f (file), l (link).

swap parts:

rnm -rs '/(.*)_(.*)\.mp3/\2_\1.mp3/' ./*
Before After
test_file.mp3 file_test.mp3
test_song.mp3 song_test.mp3

-rs takes a replace string of the form /regex/replace/modifier \1 is captured group one, \2 is captured group 2.

Replace all _ (underscore) to space:

rnm -rs '/_/ /g' ./*
Before After
test_file_123.mp3 test file 123.mp3
test_song_456.mp3 test song 456.mp3

Change all .mp3 to .MP3 (uppercase):

rnm -rs '/\.mp3/\C/g' ./*
Before After
test_file_123.mp3 test_file_123.MP3
test_song_456.mp3 test_song_456.MP3

\C (capital C) in replace part converts the matched part to uppercase

Change all before _ to (lowercase) and all after . to (uppercase):

rnm -rs '/.*_/\c/;/.*\./\C/g' ./*
Before After
TEST_file_123.mp3 test_file_123.MP3
TEST_song_456.mp3 test_song_456.MP3

\c (small c) in replace part converts to lowercase.

Insert .link at the end for files that are symbolic link:

rnm -rs '/$/.link/l' ./*

the l modifier tells it to perform the replacement only to symbolic links, other modifiers f and d are available for files and directories respectively.

rnm comes with the power of PCRE2 regex and thus you can perform almost all kinds of file name modifications using regex replace. Name string rules ( /fn/, /i/ etc..) are applicable inside regex or replace part. If you have lots of regex replace to perform, you can put them into a file and give the file path with -rs/f option. This option can be given multiple times to add multiple files. -rs option can also be given multiple times to add multiple replace string. Also replace string can be terminated with ; to add another replace string after it.

See the doc (rnm.md or rnm.html) or man page for complete details regarding regex replace.

Search for files and rename:

Search with regex:

Rename .mp3 files to .dummy:

rnm -ns '/fn/.dummy' -ss '\.mp3$' ./*
Before After
file1.mp3 file1.mp3.dummy
file2.mp3 file2.mp3.dummy
file3.mp4 file3.mp4

Rename all symbolic links to .link:

rnm -ns '/fn/.link' -ss '//l'

//l and empty search string matches anything in file name. the l modifier tells it to match link, other modifiers f and d are available for files and directories respectively.

Search with fixed string:

Rename .mp3 files to .dummy:

rnm -ns '/fn/.dummy' -ssf '.mp3' ./*
Before After
file1.mp3 file1.mp3.dummy
file2.mp3 file2.mp3.dummy
file3.mp4 file3.mp4

In this case .mp3 can match at the middle or start too.

Inverse search:

Rename all files except .mp3 to .dummy:

rnm -ns '/fn/.dummy' -ss '/\.mp3$/!' ./*
#or with fixed string:
rnm -ns '/fn/.dummy' -ssf '/.mp3/!' ./*
#for fixed string search, .mp3 will match at any place in the name
Before After
file1.mp3 file1.mp3
file2.mp3 file2.mp3
file3.mp4 file3.mp4.dummy

If you have lots of search strings, you can put them into files and add those files with -ss/f option. This option can be given multiple time to add multiple files. -ss option can also be given multiple times to add multiple search string. See the docs (rnm.md or rnm.html) or man page for more ways and details.

Sort and rename:

There are several sorting mechanisms available:

  1. -s : default sort (natural sort)
  2. -s/g : general sort
  3. -s/n : natural sort
  4. -s/mt : sort according to file modification time (recent first)
  5. -s/at : sort according to file access time (recent first)
  6. -s/ct : sort according to file status change time (recent first)
  7. -s/sz : sort according to file size (larger first)
  8. -s/d : prioritize directory when sorting
  9. -s/f : prioritize file when sorting
  10. -s/l : prioritize link when sorting
  11. -s/r : reverse the order sorted by above methods.

The default sort which comes with the option -s is natural sort (-s/n).

rnm -ns '/fn/ /id/' -s ./*

Insert file information

Add file modification time to file name:

rnm -ns '/fn/ @ /info-mtime-%d-%m-%Y %H:%I %p/' ./*
Before After
file1 file1 @ 27-01-2017 12:35 AM
file2 file2 @ 17-01-2017 10:34 PM

/info-prop-op/ is another name string rule, prop is the property name (mtime, atime, perm, uid etc..) and op is the format (optional).

Add file permission to file name:

rnm -ns '/fn/ /info-perm-ls/' ./*
Before After
dir1 dir1 drwx--x--x

perm is another property for info name string rule, op=ls is for permission resembling to ls command, oct is for octal permission.

There are lots of properties available for file info which makes all kinds of file information available. See the docs (rnm.md or rnm.html) or man page for details.

Miscellaneous examples

Add/Insert parent directory names to filename:

rnm -ns '/pd0/-/fn/' dir1/*.png
Before After
dir1/abc.png dir1/dir1-abc.png

/pd0/ is the immediate parent directory

rnm -ns '/pd1-0--/-/fn/' dir1/dir0/*.png
Before After
dir1/dir0/abc.png dir1/dir0/dir1-dir0-abc.png

/pd1-0--/ adds the directory names from /pd1/ to /pd0/ with a delimiter in-between. /pd0-1- / would become dir0 dir1 (here space is the delimiter). The general format is: /pd<from>-<to>-<delimiter>/

Index files by sorting them according to modification time:

rnm -ns '/fn/ /ir/' -s/mt ./*

The above will append index to the filenames by sorting the files according to modification time (recent first). /ir/ is reserved-index (index is reserved for skipped files), -s/mt sorts according to mtime.

Index files by sorting them according to size:

rnm -ns '/fn/ /ir/' -s/sz ./*

The above will append index to the filenames by sorting the files according to size (larger first).

Treat files, directories, links differently in a single command to rename files:

rnm -rs '/_/-/gf' -rs '/\./-/gd' -rs '/$/.link/l' ./*

This is what the above command does:

  1. Replace all underscores with hyphen for regular files (/_/-/gf).
  2. Replace all dot with hyphen for directories (/\./-/gd).
  3. Give all symbolic links a .link extension (/$/.link/l).

Search for files matching pattern1 in their name, directories matching pattern2 and links matching pattern3 and append modification time with the filename:

rnm -ns '/fn/ /info-mtime-%d-%m-%Y %H:%I %p/' -ss '/pattern1/f' -ss '/pattern2/d' -ss '/pattern3/l' ./*

rnm user manual

Other examples

rnm's People

Contributors

neurobin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

troyp lapnd

rnm's Issues

rnm error when compiling

HI,
I want to compile rnm on Ubuntu 17.04, but get the following error message when running
make
In file included from src/inout.hpp:37:0,
from src/func.hpp:35,
from src/main.cpp:33:
src/global.hpp:68:22: fatal error: jpcre2.hpp: No such file or directory
#include <jpcre2.hpp>
the jprc2.hpp is not there.
Please advise
Renate

New modifiers f and d

Two new modifiers f and d will be included with all regex type options.

  1. If modifier f is given, operation will take place only on files
  2. If modifier d is given, operation will take place only on directories
  3. If none or both are given, operation will take place on both.

Targeted for next version

typo

The usage output tells "Suprress" instead of "Suppress" for the option -qq

Force isn't applied?

rnm -rs "/-CONFLICT-1//gi" -dp 10000 --force ./*

rnm -rs "/-CONFLICT-1//gi" -dp 10000 -f ./*

`rnm -rs "/-CONFLICT-1//gi" -f -dp 10000 ./*

=> A file or directory with new name exists

Dry run option?

It would be cool to have a dry tun option to see what files would be changed

Renaming Failing on mac big sur 11.3.1

Trying to rename entire file or just extension is giving the following error.

Command being used
rnm -y -fo -dp -1 -rs '/.*/\c/' IMG_5384.PNG

W: A file or directory with new name exists:IMG_5384.PNG (@rNm:func.hpp:44)

move to directory

rnm plans to support move operation in future. The current plan is to add an extra option --destination-string or -ds to provide destination directory name/path, of course, as usual, name string rules will be applicable and some new destination string rules will be available to make up dynamic destination directory structure.

exclude directory -ed

The -ed exclude directory option currently provides a useless dummy option. The meaning of this option is going to change.

With this option users will be able to pass a list of directories that will be ignored when going into subdirectories. These directories themselves won't be renamed either.

regex and [{()}]

Hello, it's me again :)
Another lame question:
I need to rename a group of files within directory according to the following patterns:
filename [blablabla].ext -> filename (blablabla).ext
filename {blablabla}.ext -> filename (blablabla).ext
filename [*].ext -> filename (blablabla).ext
filename [#].ext -> filename (blablabla).ext
and possibly vice versa.
Smoked man/docs, tried any syntax but in vain...
Heed help please!

Cyclic renaming

rnm should (and will in some future release) support cyclic renaming.

A rudimentary algorithm:

  1. Detect if cyclic renaming is applicable when a rename fails (if target exists in the queue).
  2. If cyclic rename is possible, save the file and the target name to different queue vectors skipping it in the main queue, otherwise skip normally (with warning).
  3. Process the cyclic queue vectors separately after the main queue finishes (thus the cyclic vectors will be complete) and log every rename steps in undo files sequentially (otherwise undo won't work).

Extended numbered name string rule

This is a feature extension over existing name string rule.

Mathematical expression within numbered name string rule will be allowed, e.g /i+1/, /id*3/, /idr-4/, /i|4/, /i%4/. (| for division and % for modulus)

This is targetted to be implemented in next version.

build failure: missing aclocal-1.14

./configure works, but when I try to make, I get aclocal-1.14: command not found and WARNING: 'aclocal-1.14' is missing on your system.. If I edit the Makefile and replace "1.14" with "1.11" (the version of autoconf on my system) then it gets further, but then I get error: possibly undefined macro: AC_CHECK_HEADER_STDBOOL.

This is probably just a case of trying to run new code on an old system (Red Hat EL 6.8). The binary also did not work due to glibc/glibcxx version issues. However, if this requires autoconf ≥1.14, you might consider mentioning that in the documentation. You since it requires libstdc++6 (>=4.9.2), you might want to mention how to check that.

(To be clear, I'm not looking for help for my own benefit. I just thought you might want to know.)

rename directory only not works

rnm -rs '/./-/gd' ./*

compiled from source under centos 7

File: ‘/usr/bin/rnm’
Size: 4404320 Blocks: 8608 IO Block: 4096 regular file
Device: f900h/63744d Inode: 134304408 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-07-17 13:24:51.269169462 +0800
Modify: 2019-07-17 13:23:49.309173870 +0800
Change: 2019-07-17 13:23:49.309173870 +0800

Undo records might be better stored in $XDG_DATA_HOME (~/.local/share/)

Undo records are currently stored in ~/.cache. Many people either do not backup .cache, or clear it regularly since it is for non-essential and temporary files. Files in .cache usually regenerate themselves as needed. For log files this might be okay since they are non-critical.

Undo records are important, however, and should be stored in a directory that is persistent. Using the freedesktop standard $XDG_DATA_HOME, usually pointing to ~/.local/share, would be ideal.

This is just my opinion, but I think $XDG_DATA_HOME would be more appropriate.

multiline regex pattern in replace string doesn't work

multi line regex pattern can be formed for a replace string by including name string rule. For example:

-rs '//pd//new folder/'

If parent directory name contains newline, then /pd/ expands to a multiline string (implying the filename), thus forming a multiline regex pattern (search pattern). Currently this does not work, it fails to perform the search operation, i.e the search for that pattern returns false even if it's actually true.

Fix directory index bug.

The current code for directory index will handle upto 1 depth of directory graciously. It is supposed to fail on multiple directory.

Use a class based method to manage the directory index.

proposed feature addition and changes

  1. Add a name string rule /pd/ or /dn/ or /pdn/ as parent directory name.
  2. Allow the syntax /regex/ to be regex in -ss (search string) option, when there's no modifier.

Feature request: ignore pattern

search string is enough for this kind of thing. But a search string becomes extremely complex if it is to ignore some patterns with words or group of words. Thus a separate option for providing ignore pattern is needed.

It will be in the following format:

/ignore_pattern/modifier

Along with i modifier another modifiers f and d will be available for this case which will indicate file and directory respectively.

Precisely:

  1. If modifier i is given, pattern will ignore case.
  2. if modifier f is given, pattern will only work on files.
  3. If modifier d is given, pattern will only work on directory.
  4. If neither the f nor the d modifier is given, then the pattern will work on both files and directories
  5. If both f and d are given, then the pattern will work on both files and directories

The relevant options would be:

  1. -is : --ignore-string
  2. -isf : --ignore-string-fixed
  3. -is/f : --ignore-string-file
  4. -isf/f : --ignore-string-fixed-file

Targeted for next version

Comments and suggestions are welcome 😄

Delete fixed number of chars

Is there a possibility to delete fixed number of chars from beginning or from the end of filename?
I mean, if there is a special key for this, like
we have
filenamelong.ext
rnm -???? -2sfn filenamelong.ext -> lenamelong.ext
rnm -???? -2efn filenamelong.ext -> filenamelo.ext
where
-2sfn is "delete 2 chars from filename start" and
-2efn is "delete 2 chars from filename end"
If there are no such keys pls treat this as feature request. Thank you.

Add textsring to filename

Hello Jahidul,
Thank you for your very useful utility. Now the question:
I have a bunch of fils in dir, like
01-file01.ext
02-file02.ext
(...)
I need to rename them like this:
01-file01 (text).ext
02-file02 (text).ext
(...)
"text" is always the same (see whitespace between filename and (text)).
But when I use -ns '//n/n (text)/g/' I get " (text)" as newname. What I'm doing wrong?
Indexes and so are working good, problem only with textstring. Help!
Thanks in advance.

How to replace spaces with underscores?

Hello and thanks for a very useful utility!
I'm a newbie to *nix and my quiestion might be silly:
How can I rename group of files with spaces to the same with underline?
I mean 01 - file with spaces.ext to 01_-_file_with_spaces.ext
It seens to be easy, but reading man rnm didn't help.

reserved index and search string together

If search string is provided, reserved index reserves indexes for all files (including the files that are not complying to the search string), this is useful in some cases but seems a bit odd in my opinion. I am thinking whether to regard it as a bug or a feature.

Comments or suggestions expected...

I can't install on Debian with APT and BREW

Debian GNU/Linux 11 (bullseye)

APT
gpg: no valid OpenPGP data found.

BREW

Error: rnm: SHA256 mismatch
Expected: 668cbc6d2c0a065bb6abe8494d5a1bb3549a14cd956a44a2df9095045623ea47
  Actual: 4c2ca1b6fd180cb0f95b78fae0e647c7e57ea7647ada93e869fc230f08889db8

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.