Makefile 中的预置变量

变量名 作用
[email protected] 目标文件
$^ 所有依赖的文件
$< 第一个依赖文件

eg:

main : main.o dependent1.o dependent2.o
    gcc -o main main.o dependent1.o dependent2.o

main.o : main.c dependent1.h dependent2.h
    gcc -c main.c

使用 Makefile内置变量后:

main : main.o dependent1.o dependent2.o
    gcc -o [email protected] $^

main.o : main.c dependent1.h dependent2.h
    gcc -c $<

MAC 修改 APP 中的快捷键

修改Terminal中的Show Prevous TabShow Next Tab的快捷键。

System Preferences —-> Keyboard —->Shortcuts —->App Shortcuts

Alt none

修改后:

Alt none

关键是Menu Title一定要和APP中的名字一致。

How to change Kernel Version String

OS: Android 4.4 Kernel: 3.10.28

这里所谓的修改kernel version string并不是真的修改linux的版本号,因为那样会导致非常多的问题(比如一些驱动会不能用,等等)。所以这里修改的仅仅是/proc系统下的version,而从/proc/version中读取kernel version string是一个通常的做法,所以只需要修改这个就可以了。

kernel/fs/proc/version.c

static int version_proc_show(struct seq_file *m, void *v)
{
        seq_printf(m, linux_proc_banner,
		utsname()->sysname,
		utsname()->release,
		utsname()->version);
	return 0;
}

seq_printf和printf的功能很类似,可以输出经格式化的字符串。这里的linux_proc_banner参数实际上是一个格式化字符串,它的定义在文件kernel/init/version.c中:

const char linux_proc_banner[] =
	"%s version %s"
	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
	" (" LINUX_COMPILER ") %s\n";

所以很明显你可以通过修改上面2个文件来定制你自己的version string.

接下来看看Android的setttings中是如何来读取kernel version的:

packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java

   public static String getFormattedKernelVersion() {
        try {
            return formatKernelVersion(readLine(FILENAME_PROC_VERSION));

        } catch (IOException e) {
            Log.e(LOG_TAG,
                "IO Exception when getting kernel version for Device Info screen",
                e);

            return "Unavailable";
        }
    }

我们看到Android并不是直接返回从/proc/version中读到的内容,而是经过了formatKernelVersion()方法的处理。否则会返回Unavailable。看一下formatKernelVersion()这个方法:

    public static String formatKernelVersion(String rawKernelVersion) {
        // Example (see tests for more):
        // Linux version 3.0.31-g6fb96c9 ([email protected]) \
        //     (gcc version 4.6.x-xxx 20120106 (prerelease) (GCC) ) #1 SMP PREEMPT \
        //     Thu Jun 28 11:02:39 PDT 2012

        final String PROC_VERSION_REGEX =
            "Linux version (\\S+) " + /* group 1: "3.0.31-g6fb96c9" */
            "\\((\\S+?)\\) " +        /* group 2: "[email protected]" (kernel builder) */
            "(?:\\(gcc.+? \\)) " +    /* ignore: GCC version information */
            "(#\\d+) " +              /* group 3: "#1" */
            "(?:.*?)?" +              /* ignore: optional SMP, PREEMPT, and any CONFIG_FLAGS */
            "((Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)"; /* group 4: "Thu Jun 28 11:02:39 PDT 2012" */

        Matcher m = Pattern.compile(PROC_VERSION_REGEX).matcher(rawKernelVersion);
        if (!m.matches()) {
            Log.e(LOG_TAG, "Regex did not match on /proc/version: " + rawKernelVersion);
            return "Unavailable";
        } else if (m.groupCount() < 4) {
            Log.e(LOG_TAG, "Regex match on /proc/version only returned " + m.groupCount()
                    + " groups");
            return "Unavailable";
        }
        return m.group(1) + "\n" +                 // 3.0.31-g6fb96c9
            m.group(2) + " " + m.group(3) + "\n" + // [email protected] #1
            m.group(4);                            // Thu Jun 28 11:02:39 PDT 2012
    }

呵呵,Android系统对version string做了正则匹配,所以我们不能随意修改version string,必须要保证这里的正则表达式和上一步中修改的version string能正确匹配,否则就会是unavailable.

How to change MTP and PTP name

Android OS: 4.4.4

Sometimes, you want to change the default MTP/PTP name of your android device. If you have android source, it’s very easy.

First open the source file:

frameworks/base/media/java/android/mtp/MtpDatabase.java, Line:799(in my source), or you can search the function getDeviceProperty

    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
        switch (property) {
            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
                // writable string properties kept in shared preferences
                String value = mDeviceProperties.getString(Integer.toString(property), "");
                int length = value.length();
                if (length > 255) {
                    length = 255;
                }
                value.getChars(0, length, outStringValue, 0);
                outStringValue[length] = 0;
                return MtpConstants.RESPONSE_OK;

            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
                // use screen size as max image size
                Display display = ((WindowManager)mContext.getSystemService(
                        Context.WINDOW_SERVICE)).getDefaultDisplay();
                int width = display.getMaximumSizeDimension();
                int height = display.getMaximumSizeDimension();
                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
                outStringValue[imageSize.length()] = 0;
                return MtpConstants.RESPONSE_OK;

            default:
                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
        }
    }

Obviously, the outStringValue returned from DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME case section is the MTP name, so you can change the value whatever you want.

Then open the source file:

frameworks/av/media/mtp/MtpServer.cpp, Line:422(in my source), or you can search the function doGetDevInfo

MtpResponseCode MtpServer::doGetDeviceInfo() {
    MtpStringBuffer   string;
    char prop_value[PROPERTY_VALUE_MAX];

    MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats();
    MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats();
    MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties();

    // fill in device info
    mData.putUInt16(MTP_STANDARD_VERSION);
    if (mPtp) {
        mData.putUInt32(0);
    } else {
        // MTP Vendor Extension ID
        mData.putUInt32(6);
    }
    mData.putUInt16(MTP_STANDARD_VERSION);
    if (mPtp) {
        // no extensions
        string.set("");
    } else {
        // MTP extensions
        string.set("microsoft.com: 1.0; android.com: 1.0;");
    }
    mData.putString(string); // MTP Extensions
    mData.putUInt16(0); //Functional Mode
    mData.putAUInt16(kSupportedOperationCodes,
            sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
    mData.putAUInt16(kSupportedEventCodes,
            sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported
    mData.putAUInt16(deviceProperties); // Device Properties Supported
    mData.putAUInt16(captureFormats); // Capture Formats
    mData.putAUInt16(playbackFormats);  // Playback Formats

    property_get("ro.product.manufacturer", prop_value, "unknown manufacturer");
    string.set(prop_value);
    mData.putString(string);   // Manufacturer

    property_get("ro.product.model", prop_value, "MTP Device");
    string.set(prop_value);
    mData.putString(string);   // Model
    string.set("1.0");
    mData.putString(string);   // Device Version

    property_get("ro.serialno", prop_value, "????????");
    string.set(prop_value);
    mData.putString(string);   // Serial Number

    delete playbackFormats;
    delete captureFormats;
    delete deviceProperties;

    return MTP_RESPONSE_OK;
}

You need to change the Model String which read from the system ro.product.model property by default.

That’s all.

Linux 批量修改文件名

修改后的文件名格式:0001, 0002, …. 0100 …. 0999
Params: $1: 文件所在文件夹
$2: 目标文件的起始编号(宽度+1位), 如:宽度为4位时需要附加一个宽度位(10001)

#!/bin/bash
cd  $1 

declare -i count
count=$2

ls * | while read file;
do 
    mv "$file"  ${count:1}.jpg
    count=$((count+1))
done

#下面的代码片段不能处理文件名中的空格,当然也可以使用IFS来解决这个问题
#for file in `ls` 
#do
#    mv $file ${count:1}.jpg
#    count=$((count+1))
#done