It is possible to enable SSH and disable SFTP both globally and per user/group.
 I personally need this because I want to give access to some git repositories over SSH, and I like to disable systems that are not needed. In that case SFTP is not needed.
 Globally
 You can disable SFTP for all users in a couple of ways.
 The missing subsystem
 The SFTP daemon used by SSH can be configured through the Subsystem keyword. From the sshd_config(5) manual:
 Subsystem Configures an external subsystem (e.g. file transfer daemon). Arguments should be a subsystem name and a command (with optional arguments) to execute upon subsystem request. The command sftp-server(8) implements the “sftp” file transfer subsystem. Alternately the name “internal-sftp” implements an in-process “sftp” server. This may simplify configurations using ChrootDirectory to force a different filesystem root on clients. By default no subsystems are defined. 
 The last line suggests that it should be enough to not define any subsystem for "sftp".
 A false lie
 You could also disable SFTP by setting the SFTP daemon used by SSH to something unusable. For example, configure the "sftp" subsystem to /bin/false:
 Subsystem sftp /bin/false 
 When something would try to log in via SFTP, the SSH daemon would try to spawn the "sftp daemon" /bin/false. The /bin/false program does only one thing, and that is to return an error code. The SFTP connection attempt is effectively denied.
 Per user/group
 It is also possible to disable SFTP per user, group, or a couple of other criterias.
 This does not work if you want your user to get a regular shell prompt. Nor does it make sense, as you could circumvent most stuff if you have shell access. It will only work if you only want to give access to a specific program.
 Matching
 To match a set of users, you could configure SSH with the Match keyword. From the sshd_config(5) manual:
 Match ... The arguments to Match are one or more criteria-pattern pairs or the single token All which matches all criteria. The available criteria are User, Group, Host, LocalAddress, LocalPort, and Address. The match patterns may consist of single entries or comma-separated lists and may use the wildcard and negation operators described in the PATTERNS section of ssh_config(5). ... 
 A couple of examples:
  - Match User evamatches the "eva" user
- Match User stephen,mariamatches the "stephen" and "maria" users
- Match Group wheel,adams,simpsonsmatches the "wheel", "adams", "simpsons" groups
If you want more information, there are loads in the sshd_config(5) manual.
 Forced command
 Normally you get the user's login shell when you connect via SSH, but SSH can be configured to force a certain command. The command is forced for any SSH connection, including SFTP, and thus you might have the option to force the command you want.
 The command to force can be configured with the ForceCommand keyword. From the sshd_config(5) manual:
 ForceCommand Forces the execution of the command specified by ForceCommand, ignoring any command supplied by the client and ~/.ssh/rc if present. The command is invoked by using the user's login shell with the -c option. This applies to shell, command, or subsystem execution. It is most useful inside a Match block. The command originally supplied by the client is available in the SSH_ORIGINAL_COMMAND environment variable. Specifying a command of “internal-sftp” will force the use of an in-process sftp server that requires no support files when used with ChrootDirectory. The default is “none”. 
 So you can force the constrained command you want using ForceCommand <your command>. For example:
 Match User kim ForceCommand echo 'successful login man, congrats' 
 Example
 In my case where I want to give git access, I only need the user to have access to git-shell. This is the section that disables SFTP for my git users, along with some security options:
 Match Group git # have to do this instead of setting the login shell to `git-shell`, # to disable SFTP ForceCommand /usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND" # disable stuff we don't need AllowAgentForwarding no AllowTcpForwarding no AllowStreamLocalForwarding no PermitOpen none PermitTunnel no PermitTTY no X11Forwarding no 
   
.profilefor that sounds like the wrong solution. I believe setting up the user with an alternate shell would make a lot more sense..profiletrick to restrict access, as it is trivial to bypass. (see my answer for details)